Получить только один документ от каждого пользователя - mongoDB - PullRequest
0 голосов
/ 20 сентября 2018

Я застрял с агрегатным запросом Монго.Прямо сейчас у меня есть коллекция, которая содержит сообщения различных пользователей (чьи данные представлены в коллекции пользователей).

Мне нужен запрос, чтобы получить только одну запись от каждого пользователя (например, group by в SQL)

Данные сбора 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]]
    }

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Также вы можете использовать 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
}
])
0 голосов
/ 20 сентября 2018

$ group : будет как группа от mysql. $ first : примет первый элемент поля коллекции из группы. $ lookup действует как объединение в mysql.

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"
        }
    ]
}
0 голосов
/ 20 сентября 2018

Вы можете использовать $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"
  }}
])
...