跨多个章节同等地获取随机 MongoDB 文档

问题描述 投票:0回答:1

我有一个 MongoDB 集合,其文档结构如下:

{
    "index": 23,
    "chapter": "b11"
},
{
    "index": 25,
    "chapter": "b11"
},
{
    "index": 26,
    "chapter": "b14"
},
{
    "index": 27,
    "chapter": "b14"
},
{
    "index": 28,
    "chapter": "b16"
}

在我的集合中,我有带有“索引”字段和代表不同章节名称的“章节”字段的文档。

我需要根据特定章节名称(例如“b11”和“b16”)获取一组随机文档(例如,20 个随机文档)。我查询的章节数量可能会有所不同(例如,我可能需要获取“b11”、“b12”、“m14”等三个章节)。关键是我需要为每个指定的章节名称提供相同数量的随机文档。

我知道我需要检索的文档总数应该能被我正在查询的章节数整除。

使用 MongoDB 和 Node.js 作为后端实现这一目标的最有效方法是什么?任何代码示例或见解将不胜感激。谢谢!

我尝试使用基本查询从 MongoDB 集合中获取随机文档,但这并不能保证指定章节名称中文档的均匀分布。我期望为每个章节名称检索均衡数量的文档,但结果参差不齐。我现在正在寻找有关如何实施解决方案的指导,以确保所提供的章节名称的随机文档均匀分布。

node.js mongodb mongodb-query random-data
1个回答
0
投票

我正在考虑使用

$sample
,因为@Fourchette的评论对我来说很有意义。但是,我发现
$sample
不能接受变量作为参数。 (参见这个

所以我必须在聚合管道中执行以下操作:

  1. $match
    只有你想要的章节
  2. 获取不同的集合并计算匹配的章节
  3. $divide
    目标章节数均匀分布在提取的章节中
  4. 表现自我
    $lookup
    。使用
    $setWindowFields
    计算章节内的
    $rank
    并使用
    $rand
    作为决胜局
  5. 只选择那些有排名的人 <= num per group. e.g. if you want 10 documents in total and there are 2 matched chapters, pick those with rank <= 10 / 2 = 5
db.collection.aggregate([
  {
    "$match": {
      chapter: {
        $in: [
          "b11",
          "b14",
          "m14"
        ]
      }
    }
  },
  {
    $group: {
      _id: null,
      chapter: {
        $addToSet: "$chapter"
      }
    }
  },
  {
    $set: {
      numPerChapter: {
        "$divide": [
          10,
          {
            $size: "$chapter"
          }
        ]
      }
    }
  },
  {
    "$unwind": "$chapter"
  },
  {
    "$lookup": {
      "from": "collection",
      "let": {
        numPerChapter: "$numPerChapter"
      },
      "localField": "chapter",
      "foreignField": "chapter",
      "pipeline": [
        {
          $set: {
            randKey: {
              "$rand": {}
            }
          }
        },
        {
          "$setWindowFields": {
            "sortBy": {
              "randKey": 1
            },
            "output": {
              "rank": {
                $rank: {}
              }
            }
          }
        },
        {
          "$match": {
            $expr: {
              $lte: [
                "$randKey",
                "$$numPerChapter"
              ]
            }
          }
        },
        {
          "$unset": [
            "randKey",
            "rank"
          ]
        }
      ],
      "as": "picked"
    }
  },
  {
    "$unwind": "$picked"
  },
  {
    "$replaceRoot": {
      "newRoot": "$picked"
    }
  }
])

蒙戈游乐场

© www.soinside.com 2019 - 2024. All rights reserved.