【问题标题】:MongoDB Find All Matching array, return all not just uniqueMongoDB查找所有匹配数组,返回所有不只是唯一
【发布时间】:2018-03-22 10:22:53
【问题描述】:

我有一个用户集合。在该集合中,每个用户在输入奖品时都会将奖品 ID 存储在他们的个人资料中。下面导出一个典型的用户文档

{ 
    "_id" : ObjectId("5aacff47c67f99103bcbf693"), 
    "firstName" : "Test", 
    "lastName" : "Test", 
    "password" : "$2a$10$mJjzPFWuYPmK8A07nc284O8g9SStFpuaVzfyWOZgaCmVaomIxk5qO", 
    "email" : "test1@test.com", 
    "points" : NumberInt(6), 
    "prizes" : [
        ObjectId("5aafd1673a5b2cb294b69620"), 
        ObjectId("5aafd1673a5b2cb294b69620"), 
        ObjectId("5aafd1673a5b2cb294b69620"), 
        ObjectId("5aafd1673a5b2cb294b69620"), 
        ObjectId("5aafd1673a5b2cb294b69620"), 
        ObjectId("5ab28ca784aa6390aa5a1dba")
    ], 
    "messages" : [

    ], 
    "__v" : NumberInt(26)
}

我编写了一个 api 调用,当用户登陆他们的帐户页面时,它会找到用户并返回他们的全部奖品(奖品数组)。然后我想用这些来查询数据库以找到每个条目的标题/内容,以便它可以显示在前端。

我有两种方法

var prizes = user.prizes

       //mongo

       ids = prizes.map(function(el) { return mongoose.Types.ObjectId(el) })

       Prize.aggregate([
        { $match: { "_id": { "$in": ids } } }

      ], function(err, ret){
        if (err) {
            return res.status(500).json({
                title: 'An error occurred',
                error: err
            });

        }
          console.log(ret)
      }
    )

Prize.find( { _id: prizes }, { title: 1, content: 1 }, function(err, ret){
        if (err) {
            return res.status(500).json({
                title: 'An error occurred',
                error: err
            });

        }
console.log(ret)



       })

现在是困难的部分,这两个操作都只返回唯一的文档,(2) 而不是我想要的 6。

我想为每个条目 id 找到然后返回该奖品 id 的标题和内容,而不关心是否唯一或有响应计数,所以给我上面的用户会返回

{1x 唯一文档计数 4} {1x 唯一文档,计数 1}

或返回 6 个响应。

即使我使用了 .count(),它也只计算了 2。我知道我必须以错误的方式处理这个问题,因为 mongo 是正确的,因为我要求它找到与我通过的 id 匹配的文档它会找到 2 个匹配的 id 并为它们提供服务。

我要求它做一些不同的事情,是不是几乎破坏了它的功能?其他选择?将其包裹在 for each in 节点中并手动查询每个 id 并推送到数组?

【问题讨论】:

    标签: node.js mongodb aggregation-framework


    【解决方案1】:

    获取特定用户的奖品。

    $unwind$group 计算奖品数量,然后$lookup 获得奖品字段在 3.4 中。

    User.aggregate([
      {"$match":{"_id":mongoose.Types.ObjectId(userid)}},
      {"$unwind":"$prizes"},
      {"$group":{"_id":"$prizes","count":{"$sum":1}}},
      {"$lookup":{
        "from":"prizes", // name of the prize collection
        "localField":"_id", 
        "foreignField":"_id",
        "as":"prizes"
      }},
      {"$addFields":{"prizes":{"$arrayElemAt":["$prizes",0]}}}
    ])
    

    获得用户和奖品。

    使用$lookup 后跟$map 以防止查找字段,并使用$filter$size 计算3.4 中每个id 的奖品数量。

    类似

    User.aggregate([
      {"$match":{"_id":mongoose.Types.ObjectId(userid)}},
      {"$lookup":{
        "from":"prizes", // name of the prize collection
        "localField":"prizes",
        "foreignField":"_id",
        "as":"prizeinfo"
      }},
      {"$addFields":{
        "prizeinfo":{
          "$map":{
            "input":"$prizeinfo",
            "as":"pi",
            "in":{
              "title":"$$pi.title",
              "content":"$$pi.content",
              "count":{
                "$size":{
                  "$filter":{
                    "input":"$prizes",
                    "as":"p",
                    "cond":{"$eq":["$$pi._id","$$p"]}
                  }
                }
              }
            }
          }
        }
      }}
    ])
    

    【讨论】:

      猜你喜欢
      • 2013-05-15
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 2012-11-22
      • 2018-12-21
      • 2013-04-25
      相关资源
      最近更新 更多