MongoDB查询每次匹配返回n个文档

时间:2019-07-27 02:49:16

标签: mongodb mongodb-query aggregation-framework

我有一个资源集合,其中包含一个非唯一的群集字段(数字)。数据看起来像:

{
  { 
    _id: "0"
    cluster: 15
  },
  { 
    _id: "1"
    cluster: 4
  },
  { 
    _id: "2"
    cluster: 15
  },      
  { 
    _id: "3"
    cluster: 8
  },
  ...
}

我的目标是为每个集群匹配找到n个资源。例如,假设我要获得五个与群集1相匹配的资源,八个与群集2相匹配的资源,以及七个与群集3相匹配的资源。

目前,我可以通过发送3个单独的请求来解决该问题,例如:

db.resources.find({cluster: 1}).limit(5)

不幸的是,随着我要搜索的集群数量的增加,这变得非常低效。此外,我知道我可以按群集进行聚合和分组,但据我所知,这将仅使我能够访问每个群集的第一个(不是第n个)资源。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:0)

您可以将聚合管道与$ facet一起使用,并为$match操作中的每个集群并行运行$limit$facet阶段。最后合并$ facet阶段中的所有数组。

尝试一下:

对于集群:1,3(分别限制为2,3),您可以使用以下查询:

db.collection.aggregate([
  {
    $facet: {
      "cluster1": [
        {
          $match: {
            "cluster": 1
          }
        },
        {
          $limit: 2
        }
      ],
      "cluster2": [
        {
          $match: {
            "cluster": 3
          }
        },
        {
          $limit: 3
        }
      ]
    }
  },
  {
    $project: {
      items: {
        $concatArrays: [
          "$cluster1",
          "$cluster2"
        ]
      }
    }
  },
  {
    $unwind: "$items"
  },
  {
    $replaceRoot: {
      newRoot: "$items"
    }
  }
])

检查Mongo Playground上的结果

要概括上述聚合查询,您可以根据包含不同facetQuery及其各自{{1}的传入对象(concatArrays)来构造objcluster }}。

limits

答案 1 :(得分:-1)

这是我所知的最短的动态答案 https://mongoplayground.net/p/Ni-irGhtp85

top_n