Mongo:如何按外部重量排序

bym*_*nan 5 mongodb mongoid aggregation-framework

按照@NeilLunn优雅回答的这个问题,这是我的问题更详细.

这是一组文件,有些没有user_id.user_id表示创建文档的用户:

{ "user_id" : 11, "content" : "black", "date": somedate }
{ "user_id" : 6, "content" : "blue", "date": somedate }
{ "user_id" : 3, "content" : "red", "date": somedate }
{ "user_id" : 4, "content" : "black", "date": somedate }
{ "user_id" : 4, "content" : "blue", "date": somedate }
{ "user_id" : 90, "content" : "red", "date": somedate }
{ "user_id" : 7, "content" : "orange", "date": somedate }
{ "content" : "orange", "date": somedate }
{ "content" : "red", "date": somedate }
...
{ "user_id" : 4, "content" : "orange", "date": somedate }
{ "user_id" : 1, "content" : "orange", "date": somedate }
{ "content" : "red", "date": somedate }
{ "user_id" : 90, "content" : "purple", "date": somedate }
Run Code Online (Sandbox Code Playgroud)

前端是拉页面,所以每个页面都有10个项目,我用限制和跳过这样做,它运行得很好.

如果我们有一个登录用户,我想显示当前登录的用户文档,根据他与之交互的用户,他可能会首先发现这些文档更有趣.

当前用户可能感兴趣的用户列表按分数排序,位于mongo之外.所以第一个元素是我想要首先显示他的文档的最重要的用户,列表中的最后一个用户是最不重要的.

该列表是一个简单的数组,如下所示:[4,7,90,1].

创建此用户得分的系统不在mongo内,但如果有帮助,我可以复制数据.我也可以更改数组以包含分数.

我想要完成的是以下内容:

从列表中获取按user_id的重要性排序的文档,以便来自user_id 4的文档将是第一个显示的文档,来自user_id的文档是7秒,依此类推.如果列表中没有用户,我希望显示其余文档.像这样:

  1. user_d:4的所有文档
  2. 所有带有user_d的文档:7
  3. user_d:90的所有文档
  4. user_d:1的所有文档
  5. 所有其他文件

我该怎么做到这一点?我是从mongo那里问过多吗?

Nei*_*unn 6

给定数组[4,7,90,1]你想要的查询是这样的:

db.collection.aggregate([
   { "$project": {
       "user_id": 1,
       "content": 1,
       "date": 1,
       "weight": { "$or": [
           { "$eq": ["$user_id": 4] }, 
           { "$eq": ["$user_id": 7] }, 
           { "$eq": ["$user_id": 90] }, 
           { "$eq": ["$user_id": 1] }, 
       ]}
   }},
   { "$sort": { "weight": -1, "date": -1 } }
])
Run Code Online (Sandbox Code Playgroud)

那样做的是,对于该$or条件中包含的每个项目,该user_id字段将根据提供的值进行测试,并$eq返回1或0为true或false.

您在代码中执行的操作是针对您构建数组条件的数组中的每个项目$or.所以它只是为每个equals条件创建一个哈希结构,将它传递给一个数组并将其作为$or条件的数组值插入.

我可能应该将$ cond运算符从前面的代码中删除,所以这部分会更清楚.

这是Ruby Brain的一些代码:

userList = [4, 7, 90, 1];

orCond = [];

userList.each do |userId|
  orCond.push({ '$eq' => [ 'user_id', userId ] })
end

pipeline = [
    { '$project' => {
        'user_id' => 1,
        'content' => 1,
        'date' => 1,
        'weight' => { '$or' => orCond }
    }},
    { '$sort' => { 'weight' => -1, 'date' => -1 } }
]
Run Code Online (Sandbox Code Playgroud)

如果你想拥有单独的权重,我们将假设键值对,那么你需要使用$ cond嵌套:

db.collection.aggregate([
   { "$project": {
       "user_id": 1,
       "content": 1,
       "date": 1,
       "weight": { "$cond": [
           { "$eq": ["$user_id": 4] },
           10,
           { "$cond": [ 
               { "$eq": ["$user_id": 7] },
               9,
               { "$cond": [
                   { "$eq": ["$user_id": 90] },
                   7,
                   { "$cond": [
                       { "$eq": ["$user_id": 1] },
                       8, 
                       0
                   ]}
               ]}
           ]}
       ]}
   }},
   { "$sort": { "weight": -1, "date": -1 } }
])
Run Code Online (Sandbox Code Playgroud)

请注意,它只是一个返回值,这些不需要按顺序排列.你可以考虑一下这一代.

要生成此结构,请参见此处:

/sf/answers/1554927251/