【问题标题】:Mongoose: how to use aggregate and find togetherMongoose:如何一起使用聚合和查找
【发布时间】:2017-07-12 16:53:28
【问题描述】:

如何在 Mongoose 中同时使用 aggregatefind
即我有以下架构:

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)

如何仅使用 namefollowers_count 字段查询用户。
followers_count: followers 的长度。

在那里,我知道我们可以使用 select 只获取字段 name
我们如何获得followers 的计数?

【问题讨论】:

    标签: node.js mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    对于 MongoDB 3.6 及更高版本,使用 $expr 运算符,它允许在查询语言中使用聚合表达式:

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

    对于不兼容的版本,您可以同时使用 $match$redact 管道来查询您的集合。例如,如果要查询名称为 'development' 且 followers_count 大于 30 的 locations 集合,请运行以下聚合操作:

    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 管道。


    如果底层的 Mongo 服务器版本是 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);
    })
    

    否则,您需要在应用 $lookup 之前 $unwind 关注者数组,然后使用 $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);
    })
    

    【讨论】:

      【解决方案2】:

      你可以像下面这样使用:

      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 表示放。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-22
        • 2018-04-04
        • 1970-01-01
        • 2020-04-23
        • 1970-01-01
        • 2020-06-06
        • 2020-04-13
        • 2020-07-16
        相关资源
        最近更新 更多