Tengo un esquema Song que se ve así:
const songSchema = new mongoose.Schema({ name: { type: String, required: true, }, URL: { type: String, required: true, }, playedOn: [mongoose.Schema.Types.Date], });Y en la base de datos tengo valores como:
{ "_id" : ObjectId("6013e57d909d5252e869eac0"), "playedOn" : [ ISODate("2021-01-29T10:41:55.444Z"), ISODate("2021-01-29T10:41:55.447Z"), ISODate("2021-01-29T10:41:55.448Z"), ISODate("2021-01-29T10:41:55.450Z"), ISODate("2021-01-29T10:41:55.451Z"), ISODate("2021-01-29T10:41:55.452Z") ], "name" : "Ariana Grande - Positions", "URL" : "https://firebasestorage.googleapis.com/v0/b/reactnativeauth-sj.appspot.com/o/003.%20Ariana%20Grande%20-%20positions.mp3?alt=media&token=d206e095-6360-46c4-ad1e-40a9204ca9d0", "__v" : 1 } { "_id" : ObjectId("6013e57d909d5252e869eac1"), "playedOn" : [ ISODate("2021-01-29T10:41:53.708Z") ], "name" : "Dua Lipa - Break My Heart", "URL" : "https://firebasestorage.googleapis.com/v0/b/reactnativeauth-sj.appspot.com/o/005.%20Dua%20Lipa%20-%20Break%20My%20Heart.mp3?alt=media&token=7feea778-761c-4e0e-8840-6f60e7795651", "__v" : 1 }Primero quiero obtener las canciones más reproducidas en los últimos 7 días (por ejemplo, las 10 principales) ordenadas en orden descendente por el número de reproducciones. El resultado será como:
{name: 'Positions', _id: '39s39s', numberOfPlays: 9} {name: 'Irresistible', _id: '39s39s', numberOfPlays: 5} {name: 'Closer', _id: '39s39s', numberOfPlays: 3}He intentado cosas como:
db.songs.find({playedOn: {elemMatch: {$lt: ISODate()}}}, {_id: 1, playedOn: 1, name: 1}).pretty(); db.songs.find({playedOn: {$lt: ISODate() , $gte: ISODate("2021-01-28T09:20:37.732Z")}}, {_id: 1, playedOn: 1, name: 1}).pretty(); Y muchas cosas diferentes, pero simplemente no puedo entender la consulta que debo escribir para lo mismo. También intenté usar aggregate , pero fue en vano. Por favor, dé una dirección de cómo se puede hacer.
Usando aggregate() ,
$match fecha de inicio y fecha de finalización en $elemMatch$filter para obtener la fecha filtrada de la matriz$size para obtener el tamaño de los elementos devueltos de $filter$sort por número de numberOfPlays en orden descendente$limit para devolver 10 documentos // start date and end date set your logic as per your requirement let endDate = new Date(); let startDate = new Date(endDate); startDate.setDate(startDate.getDate() - 7); db.songs.aggregate([ { $match: { playedOn: { $elemMatch: { $gte: startDate, $lt: endDate } } } }, { $project: { name: 1, numberOfPlays: { $size: { $filter: { input: "$playedOn", cond: { $and: [ { $gte: ["$$this", startDate] }, { $lt: ["$$this", endDate] } ] } } } } } }, { $sort: { numberOfPlays: -1 } }, { $limit: 10 } ]) Usando find() A partir de MongoDB v4.4, como parte de hacer que la proyección sea consistente con la etapa $project de agregación,
.sort("-numberOfPlays").limit(10) final de la consulta