7

Как я могу использовать aggregate и find вместе в Mongoose?
т.е. у меня есть следующая схема:Mongoose: как использовать совокупность и найти вместе

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) 

Как я могу запросить пользователей только с полями name и followers_count.
followers_count: длина followers.

Там, я знаю, мы сможем использовать select, чтобы получить только поле name.
Как мы можем получить счет followers?

ответ

7

Для MongoDB 3.6 и выше, используйте оператор $expr, который позволяет использовать агрегации выражений в языке запросов:

var followers_count = 30; 
db.locations.find({ 
    "$expr": { 
     "$and": [ 
      { "$eq": ["$name", "development"] }, 
      { "$gte": [{ "$size": "$followers" }, followers_count ]} 
     ] 
    } 
}); 

Для не совместимых версий, вы можете использовать как $match и $redact трубопроводы для запроса вашей коллекции. Например, если вы хотите запросить locations коллекцию, где название «развитие» и followers_count больше, чем 30, выполните следующие укрупненные операции:

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); 
}) 

или в пределах одного трубопровода, как

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); 
}) 

Вышеуказанное вернет местоположения только с _id отзывами пользователей. Чтобы вернуть документы пользователей в качестве средства для «заполнения» массива последователей, вы можете затем добавить трубопровод $lookup.


Если базовая версия сервера Монго является 3,4 и выше, вы можете запустить конвейер как

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); 
}) 

еще вы должны были бы $unwind массив последователей перед применением $lookup, а затем перегруппировать с $group трубопровод после этого:

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); 
}) 
4

Вы можете использовать как:

db.locations.aggregate([ 
    {$match:{"your find query"}}, 
    {$project:{"your desired fields"}} 
]) 

В матче вы можете сделать такие вещи, как:

{{$match:{name:"whatever"}} 

В проекте вы можете выбрать поля, которые вы хотите, используя цифры 0 или 1 например:

{$project:{_id:1,created:0,name:1}} 

Какой 0 означает, не ставьте и 1 означает положить.