聚合中的mongodb内部查询

时间:2018-07-20 10:57:57

标签: javascript mongodb aggregation-framework

这是我收藏的简单形式。

{ 
  "_id" : "abcdfg", 
  "job_id" : "job_111", 
  "user_id" : "user_001",
  "job_createdAt" : ISODate("2018-03-02T15:02:24.122+0000"),
  "score" : 240.91185185185185
}

假设某用户发布了3个职位。 job_111, job_112, job_113。现在user1,user2,user3,user4已与job_112 and 113匹配(表示集合中有一个文档)。并且user5与所有3个作业匹配。 user6job_111上完全匹配

现在在聚合查询中,我想显示用户列表以及已匹配的作业数。但是有一个条件。与job_112 and job_113匹配的用户具有更高的优先级(因为它们是最近创建的),并且将首先显示。现在我已经这样查询了

[
  { $match: { job_id: { $in: ['job_112', 'job_113'] } } },      
  {
    $group:
      { _id: '$user_id', matched: { $sum: 1 }, score: { $max: '$score' } }
  },
  { $sort: { score: -1 } },
  { $skip: skip },
  { $limit: limit }
]

这会给我类似的东西

[
 {
   user_id: 'user1',
   matched: 2
 },
 {
   user_id: 'user2',
   matched: 2
 },
 {
   user_id: 'user4',
   matched: 2
 },
 {
   user_id: 'user5',
   matched: 2
 }
]

现在,当该列表结束时(我使用分页和聚合计数来找出它),我想显示仅与job_111匹配的用户。现在我的查询变成这样

[
  { $match: { job_id: { $in: ['job_111'] } } },      
  {
    $group:
      { _id: '$user_id', matched: { $sum: 1 }, score: { $max: '$score' } }
  },
  { $sort: { score: -1 } },
  { $skip: 0 },// << skip value resets to 0 since $in value changes
  { $limit: limit }
]

这将返回类似这样的结果

[
 {
   user_id: 'user5',
   matched: 1
 },
 {
   user_id: 'user6',
   matched: 1
 },
]

现在此结果有2个问题,我不想在列表中再次显示user5,并且其匹配的no是错误的。从技术上讲,它是3,但是返回1,因为我的查询使它的计算像1。

如何更新聚合查询,以解决该问题。我知道有一种方法可以排除将$nin放在用户字段中的用户,但是我事先没有用户列表,实际情况下可能只有几百个。有什么方法可以在运行时中找出之前在job_112 and/or job_113中匹配过的列表?

欢迎提出任何有关改进此方法或任何其他新方法的建议

2 个答案:

答案 0 :(得分:0)

您可以在一个查询中进行操作。您可以从$match开始,但要包括所有工作。然后,可以将$group$push一起使用,以收集每个用户的所有作业。在最后阶段,有两种可能:matched字段可以是表示1的{​​{1}}或$size版的$filter版的收集作业。不会少于job_111,因为这两种情况之一必须匹配,因此您可以使用$max获得11

2

答案 1 :(得分:0)

作为参考,我正在发布最终对我有用的解决方案

[
  { $match: find },
  {
    $group: {
      _id: '$user_id',
      jobs: { $push: '$job_id' },
      matched: { $sum: 1 },
      score: { $max: '$score' }
    }
  },
  {
    $project: {
      _id: '$_id',
      matched: '$matched',
      score: '$score',
      jobs: '$jobs',
      rangeType: {
        $cond: {
          if: {
            $gt: [
              {
                $size: {
                  $setIntersection: ['$jobs',['job_112', 'job_113'] ]
                }
              },
              0
            ]
          },
          then: 10,
          else: 0
        }
      }
    }
  },
  { $sort: { rangeType: -1, score: -1 } },
  { $skip: skip },
  { $limit: limit }
]
相关问题