【问题标题】:Get only one document of each user - mongoDB每个用户只获取一个文档 - mongoDB
【发布时间】:2018-09-20 18:08:40
【问题描述】:

我坚持使用 mongo 聚合查询。现在我有一个集合,其中包含各种用户的帖子(其详细信息存在于用户集合中)。

我需要一个查询来仅获取每个用户的一篇文章(如 SQL 中的 group by)

POSTS 收集数据

{
  language:'english',
  status:'A',
  desc:'Hi there',
  userId:'5b891370f43fe3302bbd8918'
},{
  language:'english',
  status:'A',
  desc:'Hi there - 2'
  userId:'5b891370f43fe3302bbd8918'
},{
  language:'english',
  status:'A',
  desc:'Hi there - 3'
  userId:'5b891370f43fe3302bbd8001'
}

这是我的查询

db.col('posts').aggregate([
    {
        $match: {
            language: 'english',
            status: "A"
        }
    }, {
        $sample: { size: 10 }
    }, {
        $sort: { _id: -1 }
    }, {
        $lookup: {
            from: 'users',
            localField: 'userId',
            foreignField: '_id',
            as: 'ownerData'
        }
    }], (err, data) => { console.log(err,data) });

期望的输出

   {
      language:'english',
      status:'A',
      desc:'Hi there',
      userId:'5b891370f43fe3302bbd8918',
      ownerData:[[object]]
    },{
      language:'english',
      status:'A',
      desc:'Hi there - 3'
      userId:'5b891370f43fe3302bbd8001',
      ownerData:[[object]]
    }

【问题讨论】:

  • 按用户分组,并获取每个组的第一个元素

标签: node.js mongodb mongoose aggregation-framework


【解决方案1】:

$group:将作为mysql的group by。 $first:将从组中获取集合字段的第一个元素。 $lookup 在 mysql 中充当 join。

db.tempdate.aggregate([ 
    { $group : 
        { 
          _id : "$userId", 
          language : { $first: '$language' }, 
          status : { $first: '$status' },  
          desc : { $first: '$desc' } 
        } 
     },
     { $lookup: 
        { 
            from: "user", 
            localField: "_id", 
            foreignField: "user_id",
            as: "userData" 
         } 
     }
 ]).pretty();`

Output

`{
    "_id" : "5b891370f43fe3302bbd8001",
    "language" : "english",
    "status" : "A",
    "desc" : "Hi there - 3",
    "userData" : [
        {
            "_id" : ObjectId("5ba3633a12b8613823f3056e"),
            "user_id" : "5b891370f43fe3302bbd8001",
            "name" : "Bhuwan"
        }
    ]
}
{
    "_id" : "5b891370f43fe3302bbd8918",
    "language" : "english",
    "status" : "A",
    "desc" : "Hi there",
    "userData" : [
        {
            "_id" : ObjectId("5ba3634612b8613823f3056f"),
            "user_id" : "5b891370f43fe3302bbd8918",
            "name" : "Harry"
        }
    ]
}

【讨论】:

    【解决方案2】:

    另外,您可以使用group$last

    db.getCollection('posts').aggregate([
      { "$match": { "language": 'english', "status": "A" }},
      { "$group": {
        "_id": "$userId",
         "primaryId" : { "$last": "$_id" },
        "language": { "$last": "$language" },
        "status": { "$last": "$status" },
        "desc": { "$last": "$desc" }
      }},
      { "$lookup": {
        "from": "users",
        "localField": "_id",
        "foreignField": "_id",
        "as": "ownerData"
      }},
      { $unwind:{path: '$ownerData',preserveNullAndEmptyArrays: true} //to convert ownerData to json object
    }
    ])
    

    【讨论】:

      【解决方案3】:

      您可以将$group 聚合阶段用于不同的userId,然后使用$lookup 获取用户数据。

      db.col('posts').aggregate([
        { "$match": { "language": 'english', "status": "A" }},
        { "$sample": { "size": 10 }},
        { "$sort": { "_id": -1 }},
        { "$group": {
          "_id": "$userId",
          "language": { "$first": "$language" },
          "status": { "$first": "$status" },
          "desc": { "$first": "$desc" }
        }},
        { "$lookup": {
          "from": "users",
          "localField": "_id",
          "foreignField": "_id",
          "as": "ownerData"
        }}
      ])
      

      【讨论】:

        猜你喜欢
        • 2017-05-16
        • 2021-02-12
        • 1970-01-01
        • 2021-08-17
        • 1970-01-01
        • 2021-08-22
        • 2021-04-25
        • 2021-05-28
        • 1970-01-01
        相关资源
        最近更新 更多