Comment puis-je utiliser agrégat et find
ensemble dans Mongoose?
C'est-à-dire que j'ai le schéma suivant:
const schema = new Mongoose.Schema({
created: { type: Date, default: Date.now() },
name: { type: String, default: 'development' }
followers: [{ type: Mongoose.Schema.ObjectId, ref: 'Users'}]
...
})
export default Mongoose.model('Locations', schema)
Comment interroger les utilisateurs uniquement avec les champs name
et followers_count
.followers_count
: la longueur de followers
.
Là, je sais que nous pouvons utiliser select pour obtenir uniquement le champ name
.
Comment pouvons-nous obtenir le nombre de followers
?
Pour MongoDB 3.6 et versions ultérieures, utilisez le $expr
opérateur permettant d’utiliser des expressions d’agrégation dans le langage de requête:
var followers_count = 30;
db.locations.find({
"$expr": {
"$and": [
{ "$eq": ["$name", "development"] },
{ "$gte": [{ "$size": "$followers" }, followers_count ]}
]
}
});
Pour les versions non compatibles, vous pouvez utiliser à la fois le $match
et $redact
des pipelines pour interroger votre collection. Par exemple, si vous souhaitez interroger la collection locations
où le nom est 'développement' et followers_count
est supérieur à 30, exécutez l'opération d'agrégation suivante:
const followers_count = 30;
Locations.aggregate([
{ "$match": { "name": "development" } },
{
"$redact": {
"$cond": [
{ "$gte": [ { "$size": "$followers" }, followers_count ] },
"$$KEEP",
"$$Prune"
]
}
}
]).exec((err, locations) => {
if (err) throw err;
console.log(locations);
})
ou dans un seul pipeline comme
Locations.aggregate([
{
"$redact": {
"$cond": [
{
"$and": [
{ "$eq": ["$name", "development"] },
{ "$gte": [ { "$size": "$followers" }, followers_count ] }
]
},
"$$KEEP",
"$$Prune"
]
}
}
]).exec((err, locations) => {
if (err) throw err;
console.log(locations);
})
Ce qui précède renverra les emplacements avec uniquement le _id
références des utilisateurs. Pour retourner les documents de l'utilisateur comme moyen de "peupler" le tableau de followers, vous pouvez ensuite ajouter le $lookup
pipeline.
Si la version de serveur Mongo sous-jacente est 3.4 et plus récente, vous pouvez exécuter le pipeline en tant que
let followers_count = 30;
Locations.aggregate([
{ "$match": { "name": "development" } },
{
"$redact": {
"$cond": [
{ "$gte": [ { "$size": "$followers" }, followers_count ] },
"$$KEEP",
"$$Prune"
]
}
},
{
"$lookup": {
"from": "users",
"localField": "followers",
"foreignField": "_id",
"as": "followers"
}
}
]).exec((err, locations) => {
if (err) throw err;
console.log(locations);
})
sinon vous auriez besoin de $unwind
le tableau des adeptes avant d’appliquer $lookup
puis regrouper avec $group
pipeline après cela:
let followers_count = 30;
Locations.aggregate([
{ "$match": { "name": "development" } },
{
"$redact": {
"$cond": [
{ "$gte": [ { "$size": "$followers" }, followers_count ] },
"$$KEEP",
"$$Prune"
]
}
},
{ "$unwind": "$followers" },
{
"$lookup": {
"from": "users",
"localField": "followers",
"foreignField": "_id",
"as": "follower"
}
},
{ "$unwind": "$follower" },
{
"$group": {
"_id": "$_id",
"created": { "$first": "$created" },
"name": { "$first": "$name" },
"followers": { "$Push": "$follower" }
}
}
]).exec((err, locations) => {
if (err) throw err;
console.log(locations);
})
Vous pouvez utiliser comme suit:
db.locations.aggregate([
{$match:{"your find query"}},
{$project:{"your desired fields"}}
])
Dans le match, vous pouvez faire des choses comme:
{{$match:{name:"whatever"}}
Dans le projet, vous pouvez sélectionner les champs souhaités en utilisant les chiffres 0 ou 1, comme suit:
{$project:{_id:1,created:0,name:1}}
Quel 0 signifie, ne pas mettre et 1 signifie mettre.