【问题标题】:How can I get all the doc ids in MongoDB?如何获取 MongoDB 中的所有文档 ID?
【发布时间】:2022-01-09 04:47:31
【问题描述】:

如何获取 MongoDB 中所有文档 ID 的数组?我只需要一组 id 而不是文档内容。

【问题讨论】:

  • db.c.find({},{_id:1}); 应该这样做
  • find() 返回的是一个游标,无论如何我都没有看到从返回的游标中检索所有 id(但不是文档,如 cursor.toArray() 所做的)。
  • 由于 MongoDB 在 BSON 中通信,我认为如果不耗尽游标然后过滤掉值,您想要什么是可能的

标签: mongodb


【解决方案1】:

您可以在 Mongo shell 中通过在光标上调用 map 来执行此操作,如下所示:

var a = db.c.find({}, {_id:1}).map(function(item){ return item._id; })

结果是a 是一个仅包含_id 值的数组。

它在 Node 中的工作方式是类似的。

(这是 MongoDB 节点驱动程序 v2.2 和节点 v6.7.0

db.collection('...')
  .find(...)
  .project( {_id: 1} )
  .map(x => x._id)
  .toArray();

记得放map before toArray 因为这个map不是JavaScript的map函数,但它是MongoDB提供的,它在数据库中运行之前返回光标。

【讨论】:

    【解决方案2】:

    一种方法是简单地使用 runCommand API。

    db.runCommand ( { distinct: "distinct", key: "_id" } )
    

    这给了你这样的东西:

    {
        "values" : [
            ObjectId("54cfcf93e2b8994c25077924"),
            ObjectId("54d672d819f899c704b21ef4"),
            ObjectId("54d6732319f899c704b21ef5"),
            ObjectId("54d6732319f899c704b21ef6"),
            ObjectId("54d6732319f899c704b21ef7"),
            ObjectId("54d6732319f899c704b21ef8"),
            ObjectId("54d6732319f899c704b21ef9")
        ],
        "stats" : {
            "n" : 7,
            "nscanned" : 7,
            "nscannedObjects" : 0,
            "timems" : 2,
            "cursor" : "DistinctCursor"
        },
        "ok" : 1
    }
    

    但是,使用实际的distinct API 还有一个更好的方法:

     var ids = db.distinct.distinct('_id', {}, {});
    

    这只是给你一个 id 数组:

    [
        ObjectId("54cfcf93e2b8994c25077924"),
        ObjectId("54d672d819f899c704b21ef4"),
        ObjectId("54d6732319f899c704b21ef5"),
        ObjectId("54d6732319f899c704b21ef6"),
        ObjectId("54d6732319f899c704b21ef7"),
        ObjectId("54d6732319f899c704b21ef8"),
        ObjectId("54d6732319f899c704b21ef9")
    ]
    

    不确定第一个版本,但 Node.js 驱动程序肯定支持后者(我看到你提到你想使用它)。看起来像这样:

    db.collection('c').distinct('_id', {}, {}, function (err, result) {
        // result is your array of ids
    })
    

    【讨论】:

    • 当 id 已经是唯一的时候,不会给服务器 esp 带来不必要的负载吗?
    • @comiventor 这是可能的......但我想 OP 只想在一个小数据集上执行此操作,所以这可能没什么大不了的。另一方面,它避免了必须循环所有结果以将它们缓冲回客户端上的数组。
    • 这可能/将会在大型数据集上导致类似Command failed with error 17217: 'distinct too big, 16mb cap' on server 的错误
    【解决方案3】:

    我还想知道如何使用 MongoDB Node.JS 驱动程序来执行此操作,例如 @user2793120。其他人说他应该用 .each 遍历结果,这对我来说似乎效率很低。我改用MongoDB's aggregation

        myCollection.aggregate([
                {$match: {ANY SEARCHING CRITERIA FOLLOWING $match'S RULES} },
                {$sort: {ANY SORTING CRITERIA, FOLLOWING $sort'S RULES}},
                {$group: {_id:null, ids: {$addToSet: "$_id"}}}
        ]).exec()
    

    排序阶段是可选的。如果您想要所有集合的 _id,则匹配一个。如果你 console.log 结果,你会看到类似:

        [ { _id: null, ids: [ '56e05a832f3caaf218b57a90', '56e05a832f3caaf218b57a91', '56e05a832f3caaf218b57a92' ] } ]
    

    然后在其他地方使用 result[0].ids 的内容。

    这里的关键部分是$group section。您必须为 _id 定义一个 null 值(否则,聚合将崩溃),并创建一个包含所有 _id 的新数组字段。如果您不介意重复的 id(根据您在 $match 阶段中使用的搜索条件,并假设您正在对 _id 以外的字段进行分组,该字段也有另一个文档 _id),您可以使用 $push 而不是 @987654324 @。

    【讨论】:

      【解决方案4】:

      在 mongo 控制台上执行此操作的另一种方法是:

      var arr=[]
      db.c.find({},{_id:1}).forEach(function(doc){arr.push(doc._id)})
      printjson(arr)
      

      希望对你有帮助!!!

      谢谢!!!

      【讨论】:

        【解决方案5】:

        我为此苦苦挣扎了很长时间,我之所以回答这个问题是因为我有一个重要的提示。很明显:

        db.c.find({},{_id:1});
        

        会是答案。

        它确实奏效了。它会找到前 101 个文档,然后应用程序会暂停。我没有让它继续下去。这既是在使用 MongoOperations 的 Java 中,也是在 Mongo 命令行中。

        我查看了 mongo 日志,发现它正在对大量大型文档进行 colscan。我想,疯了,我在投影总是被索引的 _id 那么它为什么要尝试 colscan 呢?

        我不知道为什么会这样做,但解决方案很简单:

        db.c.find({},{_id:1}).hint({_id:1});
        

        或在 Java 中:

        query.withHint("{_id:1}");
        

        然后它就可以正常进行了,使用流样式:

        createStreamFromIterator(mongoOperations.stream(query, MortgageDocument.class)).
             map(MortgageDocument::getId).forEach(transformer);
        

        Mongo 可以做一些好事,但它也可能陷入非常混乱的状态。至少这是我目前的经验。

        【讨论】:

        • 您在 mongosh 示例中缺少 {} db.c.find({},{_id:1}).hint({_id:1});
        • 谢谢,我编辑了。仍然不确定hint() 在这方面做了什么,但它需要它。
        【解决方案6】:

        尝试使用聚合管道,如下所示:

        db.collection.aggregate([
        { $match: { deletedAt: null }},
        { $group: { _id: "$_id"}}
        

        ])

        这个 gona 返回一个具有这种结构的文档数组

        _id: ObjectId("5fc98977fda32e3458c97edd")
        

        【讨论】:

          【解决方案7】:

          我有类似的要求来获取具有 50+ 百万行的集合的 ID。我尝试了很多方法。结果证明,获取 id 的最快方法是仅使用 id 进行 mongoexport。

          【讨论】:

            【解决方案8】:

            上面的一个例子对我有用,只是稍作调整。我省略了第二个对象,因为我尝试使用我的 Mongoose 架构。

            const idArray = await Model.distinct('_id', {}, function (err, result) {
                // result is your array of ids
                return result;
            });
            

            【讨论】:

              猜你喜欢
              • 2017-09-14
              • 2022-08-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多