【问题标题】:How to join and sort few collections in one pipeline in Mongo如何在 Mongo 的一个管道中加入和排序几个集合
【发布时间】:2017-04-13 08:07:24
【问题描述】:

我想制作一个用户列表,按照他们背后的关系排序。

为此,我需要比较 3 个集合的 ID 以按顺序排序 -

first: '收到的请求',

second: '发送请求到',

第三个:“朋友”,

第四个:'其他'

更新: 输入

识别用户背后关系的集合

db.friends.find({userId: currentUser});
    // {"_id" : "qwC7LrtaZtQsShtzT", "userId" : "rbrwhh2AQY8mzmzd3", "friendId" : "4y7pG7p2gcGgm5ayj",} 
db.requests.find({userId: currentUser});
   // {"_id" : "PgC7LrtaZtQsShtzT", "userId" : "tHuxnWxFLHvcpRgHb", "requesterId" : "jZagPF7bd4aW8agXb",}

包含所有用户及其信息的主要集合

db.users.find({userId: currentUser});
      // {"_id" : "4y7pG7p2gcGgm5ayj", profile: {name: 'Andrey', second: 'Andrey'}} -> Same person(id) like in 'friends' collection.
     // {"_id": "tHuxnWxFLHvcpRgHb", profile: {name: 'Erick', second: 'Erick'} -> same person who have receive request. 

现在我需要聚合“用户”集合,定义与前两个集合(朋友、请求)匹配的分数。

我试着这样做

db.users.aggregate([
    // here i tried to compare _id and requesterId to fetch all who received request from me:
    {$lookup: {from: 'requests', localField: "_id", foreignField: "requesterId", as: "sentRequest"}},
    {$unwind: '$sentRequest'},
    {$project: {_id: '$sentRequest.userId', profile: 1, count: {$add: [2]}}},
    // And here I tried to get all friends
    {$lookup: {from: 'requests', localField: "_id", foreignField: "friendId", as: "friends"}},
    {$unwind: '$friends'},
    {$project: {_id: '$friends.userId', profile: '$profile', count: {$add: [3]}}}

]);

但结果我只得到了最后一部分(朋友)和另一个问题

[ { _id: 'rbrwhh2AQY8mzmzd3', //this field is responds to person which I looking for
 profile: //But profile data is given from .users and its not respont to person with given id
  { firstName: 'Andrey', 
    lastName: 'Andrey',
   userImg: '/img/user.jpg',
   userDescription: null },
  count: 3 } ]

更新

预期结果

//Given: 3 collections
db.users -> provide all additional info about all users
db.requests -> groups IDs of two users 'requester' and 'receiver'
db.friends -> groups IDs of two users 'friend' and 'user', document has pair where value are swapped (but it's not important in this task);

//Need to combine all of this three collections in one queue, to sort users by their relationships between them, in kind of this list:
// 1 - Requests; 2 - Friends; 3 - Other users


// Expected result:
[   
    // I've got request From:
    { "_id": "tHuxnWxFLHvcpRgHb", // _id must be equal to user who sent request and _id from db.users
        "profile": // this value used from db.users
        {   
            "firstName": "Ana", 
            "lastName": "de Armas",
            "userImg": "/img/user.jpg",
            "userDescription": null 
        },
            "weight": 4 // given value to make sorting then
    },
    // I sent request To: 
    { "_id": "4y7pG7p2gcGgm5ayj", 
        "profile": 
        {   
            "firstName": "John", 
            "lastName": "Bonjovi",
            "userImg": "/img/user.jpg",
            "userDescription": null 
        },
            "weight": 3 
    },
    // My friend:
    { "_id": "jZagPF7bd4aW8agXb", 
        "profile": 
        {   
            "firstName": "Jessica", 
            "lastName": "Alba",
            "userImg": "/img/user.jpg",
            "userDescription": null 
        },
            "weight": 2 
    },
    // Unknown user:
    { "_id": "DdX8sPuAoZqKpa6nH", 
        "profile": 
        {   
            "firstName": "Sheldon", 
            "lastName": "Cooper",
            "userImg": "/img/user.jpg",
            "userDescription": null 
        },
            "weight": 1 
    }
]

我尝试将聚合与 $lookup 一起使用 - 但它不适用于 3 个集合。

结果我需要返回队列,在哪里可以在新加入的集合中设置新字段 - 权重。有可能按此字段排序。

【问题讨论】:

  • 请提供一些数据以及您对这些数据的预期结果
  • stackoverflow.com/q/40868364/2683814 在这里回答一些类似的问题。
  • @veeram 感谢您的回复。它有用的例子。但它并不完全有效。我已经更新了我的问题,在我的任务中我是如何尝试使用你的示例的。也许有些事情是无法理解的,所以你可以问我。谢谢!
  • 如果你能添加预期的输出会非常有帮助
  • @Veeram,我已经更新了问题。谢谢!

标签: mongodb sorting meteor


【解决方案1】:

最新的 Mongo 3.4 版本,您将使用 $facet 跨多个聚合管道处理相同的数据,并将所有聚合的结果连接到单个输出。

db.users.aggregate([
    { "$match": { "_id":1} },
    {
        "$facet": {
            "Received": [
                 {$lookup: {from: 'requests', localField: "_id", foreignField: "userId", as: "receivedRequest"}},
                 {$unwind: '$receivedRequest'},
                 {$lookup: {from: 'users', localField: "receivedRequest.requesterId", foreignField: "_id", as: "receivedUser"}},
                 {$project: {_id: '$receivedRequest.requesterId', profile: '$receivedUser.profile', weight: {$add: [4]}}}
            ],
            "Sent": [
                 {$lookup: {from: 'requests', localField: "_id", foreignField: "requesterId", as: "sentRequest"}},
                 {$unwind: '$sentRequest'},
                 {$lookup: {from: 'users', localField: "sentRequest.userId", foreignField: "_id", as: "sendUser"}},
                 {$project: {_id: '$sentRequest.userId', profile: '$sendUser.profile', weight: {$add: [3]}}}
            ],
            "Friends": [
                 {$lookup: {from: 'friends', localField: "_id", foreignField: "userId", as: "friends"}},
                 {$unwind: '$friends'},
                 {$lookup: {from: 'users', localField: "friends.friendId", foreignField: "_id", as: "friendUser"}},
                 {$project: {_id: '$friends.friendId', profile: '$friendUser.profile', weight: {$add: [2]}}}
            ],
            "Others": [
                {$lookup: {from: 'friends', localField: "_id", foreignField: "friendId", as: "others"}},
                 {$unwind: '$others'},
                 {$lookup: {from: 'users', localField: "others.userId", foreignField: "_id", as: "other"}},
                 {$project: {_id: '$others.userId', profile: '$other.profile', weight: {$add: [1]}}}
            ]
        }
    }
]).pretty()

样本输出:

{
        "Received" : [
                {
                        "_id" : 3,
                        "profile" : [
                                {
                                        "name" : "John"
                                }
                        ],
                        "weight" : 4
                }
        ],
        "Sent" : [
                {
                        "_id" : 4,
                        "profile" : [
                                {
                                        "name" : "Jessica"
                                }
                        ],
                        "weight" : 3
                }
        ],
        "Friends" : [
                {
                        "_id" : 2,
                        "profile" : [
                                {
                                        "name" : "Ana"
                                }
                        ],
                        "weight" : 2
                }
        ],
        "Others" : [
                {
                        "_id" : 5,
                        "profile" : [
                                {
                                        "name" : "Sheldon"
                                }
                        ],
                        "weight" : 1
                }
        ]
}

【讨论】:

  • 这将是一个很棒的功能,但我正在使用流星,不幸的是,这种改进很快就会不支持。也许你知道我该如何以另一种方式解决这个问题?我尝试使用“if else”语句对 id 数组进行排序,但是当我从集合中获取数据时,它会在标准顺序的情况下返回我,而不管数组中每个元素的位置。
  • 请将您尝试过的内容添加到帖子中。也许我可以尝试以此为基础。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
  • 2017-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-31
相关资源
最近更新 更多