27

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

4

8 回答 8

63

您可以在 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 前面 toArray,因为这map不是 JavaScriptmap函数,而是 MongoDB 提供的函数,它在返回游标之前在数据库中运行。

于 2013-09-18T21:56:04.453 回答
12

一种方法是简单地使用 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
})
于 2015-02-08T02:13:43.013 回答
6

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

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

于 2016-03-10T17:14:10.203 回答
4

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

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

希望有帮助!!!

谢谢!!!

于 2013-09-19T05:52:12.177 回答
4

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

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 可以做一些好事,但它也可能陷入非常混乱的状态。至少这是我迄今为止的经验。

于 2019-02-27T00:18:02.330 回答
1

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

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

])

这将返回具有此结构的文档数组

_id: ObjectId("5fc98977fda32e3458c97edd")
于 2020-12-04T15:33:04.433 回答
0

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

于 2020-06-04T15:56:35.467 回答
0

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

const idArray = await Model.distinct('_id', {}, function (err, result) {
    // result is your array of ids
    return result;
});
于 2021-06-15T05:42:09.823 回答