如何获取 MongoDB 中的所有文档 ID?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18881982/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 13:25:25  来源:igfitidea点击:

How can I get all the doc ids in MongoDB?

mongodb

提问by user2793120

How can I get an array of all the doc ids in MongoDB? I only need a set of ids but not the doc contents.

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

回答by JohnnyHK

You can do this in the Mongo shell by calling mapon the cursor like this:

您可以在 Mongo shell 中通过map像这样调用光标来执行此操作:

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

The result is that ais an array of just the _idvalues.

结果是a一个只有_id值的数组。

The way it works in Node is similar.

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

(This is MongoDB Node driver v2.2, and Node v6.7.0)

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

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

Remember to put mapbeforetoArrayas this mapis NOT the JavaScript mapfunction, but it is the one provided by MongoDB and it runs within the database before the cursor is returned.

记住放在map前面,toArray因为这map不是 JavaScriptmap函数,但它是 MongoDB 提供的函数,它在返回游标之前在数据库中运行。

回答by whitfin

One way is to simply use the runCommand API.

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

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

which gives you something like this:

这给了你这样的东西:

{
    "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
}

However, there's an even nicer way using the actual distinctAPI:

但是,使用实际distinctAPI有更好的方法:

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

which just gives you an array of ids:

它只是给你一个 id 数组:

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

Not sure about the first version, but the latter is definitely supported in the Node.js driver (which I saw you mention you wanted to use). That would look something like this:

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

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

回答by Lucio Mollinedo

I also was wondering how to do this with the MongoDB Node.JS driver, like @user2793120. Someone else said he should iterate through the results with .each which seemed highly inefficient to me. I used MongoDB's aggregationinstead:

我也想知道如何使用 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()

The sorting phase is optional. The match one as well if you want all the collection's _ids. If you console.log the result, you'd see something like:

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

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

Then just use the contents of result[0].ids somewhere else.

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

The key part here is the $group section. You must define a value of null for _id (otherwise, the aggregation will crash), and create a new array field with all the _ids. If you don't mind having duplicated ids (according to your search criteria used in the $match phase, and assuming you are grouping a field other than _id which also has another document _id), you can use $pushinstead of $addToSet.

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

回答by Anuj Aneja

Another way to do this on mongo console could be:

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

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

Hope that helps!!!

希望有帮助!!!

Thanks!!!

谢谢!!!

回答by user2959589

I struggled with this for a long time, and I'm answering this because I've got an important hint. It seemed obvious that:

我为此挣扎了很长时间,我回答这个问题是因为我得到了一个重要提示。很明显:

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

would be the answer.

将是答案。

It worked, sort of. It would find the first 101 documents and then the application would pause. I didn't let it keep going. This was both in Java using MongoOperations and also on the Mongo command line.

它起作用了,有点。它将找到前 101 个文档,然后应用程序将暂停。我没有让它继续下去。这是在 Java 中使用 MongoOperations 和 Mongo 命令行。

I looked at the mongo logs and saw it's doing a colscan, on a big collection of big documents. I thought, crazy, I'm projecting the _id which is always indexed so why would it attempt a colscan?

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

I have no idea why it would do that, but the solution is simple:

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

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

or in Java:

或在 Java 中:

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

Then it was able to proceed along as normal, using stream style:

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

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

Mongo can do some good things and it can also get stuck in really confusing ways. At least that's my experience so far.

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