如何在MongoDB集合中为所有文档选择单个字段?

390

在我的MongoDB数据库中,有一个包含10条记录、拥有字段nameroll的学生集合。其中一条记录如下:

{
    "_id" : ObjectId("53d9feff55d6b4dd1171dd9e"),
    "name" : "Swati",
    "roll" : "80",
}

我想要从集合中检索出所有10条记录中的roll字段,就像传统数据库中所做的那样:

SELECT roll FROM student

我查阅了很多博客,但所有的博客都要求查询中必须包含 WHERE 子句,例如:

经过许多博客的研究,发现所有的查询语句都必须包含 WHERE 子句,例如:

db.students.find({ "roll": { $gt: 70 })

该查询等效于:

SELECT * FROM student WHERE roll > 70

我的要求是查找一个键,而不需要任何条件。那么,这种查询操作是什么。


@NeilLunn 感谢您提供的链接 SQL to MongoDB Mapping。不知道我怎么错过了这个。 - Shipra Swati
今天是我在MongoDB的第一天,我还没有理解为什么在db.student.find({},{roll:1})1是必需的,为什么它不能设计成像这样db.student.find({},{roll})。如果我们给除了1之外的任何其他值,会发生什么情况呢? - Arun
2
@Arun 因为它是JSON格式,所以我认为是这样的。 - do thuan
@ShipraSwati 如果您接受问题的答案,将来参考会非常有帮助。 - Naman
25个回答

489

根据MongoDB文档,投影可以明确包含几个字段。在下面的操作中,find()方法返回符合查询条件的所有文档。在结果集中,只有项目和数量字段以及默认情况下的_id字段会返回匹配的文档。

db.inventory.find( { type: 'food' }, { item: 1, qty: 1 } )

这个来自Mongo团队的例子中,返回的文档将只包含itemqty_id字段。


因此,您应该能够发出像这样的语句:

db.students.find({}, {roll:1, _id:0})
以上语句将选择 students 集合中的所有文档,并且返回的文档将只返回 roll 字段(并排除 _id 字段)。
如果我们不提到 _id:0,则返回的字段将是 roll 和 _id。 '_id' 字段默认始终显示。因此,我们需要明确提到 _id:0 以及 roll。

14
无法在谷歌上找到答案,不妨试一下。如果你只想要一个字段,但文档有10个字段,你必须显式地将其余9个字段设置为0吗?编辑:算了,排除_id{field_I_want:1, _id:0}似乎可行。 - Karl Tryggvason
如果我使用投影,是否可以添加一个字段并更新文档? - chovy
11
所有回答实际上都没有提到以下内容:注意:除了_id字段,您不能在投影文档中同时结合包含和排除语句。这可能会对你们中的一些人很有趣。 (来源) - j3141592653589793238
7
如果有人在使用时遇到问题,可能是因为您正在运行较新版本的mongodb驱动程序,该驱动程序稍微更改了API:db.students.find({}, { projection : { roll:1, _id:0 } })现在您必须在"projection"键上指定要包含/排除的字段。文档:http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#find - Mats
如果对其他人来说(就像对我来说一样)01不是完全明显的,那么在这里它们代表布尔值。{roll:1, _id:0}等同于{roll:true, _id:false} - undefined

295

获取表中的所有数据

db.student.find({})

SELECT * FROM student WHERE _id NOT NULL


获取表中除_id列外的所有数据

db.student.find({}, {_id:0})

选择学生表中的姓名和学号


从一个带有_id的字段中获取所有数据

db.student.find({}, {roll:1})

选择 student 表中的 id 和 roll 字段


获取一个字段中除去 _id 以外的所有数据

db.student.find({}, {roll:1, _id:0})

从学生表中选择学号数据


使用where子句查找指定的数据

db.student.find({roll: 80})
SELECT * FROM students WHERE roll > '80'
db.student.find({ "roll": { $gt: 70 }}) // $gt is greater than 

查询学生表中所有滚动号大于70的记录。


使用Where子句和大于条件查找数据

db.student.find({ "roll": { $gte: 70 }}) // $gte is greater than or equal

SELECT * FROM student WHERE roll >= '70'


使用 WHERE 子句和小于等于条件查找数据

db.student.find({ "roll": { $lte: 70 }}) // $lte is less than or equal

SELECT * FROM student WHERE roll <= '70'


使用where子句和小于等于条件来查找数据

db.student.find({ "roll": { $lt: 70 }})  // $lt is less than

选择所有滚动编号小于70的学生。


8
想要补充一下,因为您的回答帮助我找到了解决方法,显示除_id之外的所有属性将是db.student.find({}, {_id:0})。感谢您的帮助。 - user8675309
在排除ID时出现错误:“无法在包含投影中对字段进行排除”。 - Himanshu Tariyal
@HimanshuTariyal 如果存在包含项,则只能排除 _id,而不能排除 id 或其他任何内容。 - Matthew Read

78

我认为mattingly890给出了正确的答案,这里再举一个例子并附带上相应的模式/命令。

db.collection.find({}, {your_key:1, _id:0})

> db.mycollection.find().pretty();

{
    "_id": ObjectId("54ffca63cea5644e7cda8e1a"),
    "host": "google",
    "ip": "1.1.192.1"
}
db.mycollection.find({},{ "_id": 0, "host": 1 }).pretty();

展示Mongo的输出以及返回值作为示例。 - grepit
伙计,你给我投了反对票是因为我在答案中包含了截图吗? - grepit
1
是的,而且也因为我没有看到你的回答从@therealrootuser的回答中带来了什么新的东西。 - Guillaume Lebreton

23

给你三种方法,从最简单到最无聊:

db.student.find({}, 'roll _id'); // <--- Just multiple fields name space separated
// OR
db.student.find({}).select('roll _id'); // <--- Just multiple fields name space separated
// OR
db.student.find({}, {'roll' : 1 , '_id' : 1 ); // <---- Old lengthy boring way

使用-运算符来删除特定字段:

db.student.find({}).select('roll -_id') // <--- Will remove id from result

2
我认为你提到的命令来自mongoose而不是mongodb,除了第三个。 - Ashish Sharma

18

虽然 gowtham 的回答 是完整的,但需要注意的是这些命令可能因为使用的不同API而有所不同(对于那些没有使用 mongo's shell 的情况)。

请查阅文档链接获取详细信息。

例如,Nodejs有一个称为`projection`的方法,你可以将其附加到你的查找函数中以进行项目投影。

按照相同的示例设置,类似以下命令可用于Node:

db.student.find({}).project({roll:1})

SELECT _id, roll FROM student

或者
db.student.find({}).project({roll:1, _id: 0})

SELECT roll FROM student

等等。

再次提醒针对nodejs用户,在使用.then命令之前,不要忘记(如果您之前使用过此API,应该已经熟悉)使用toArray来附加。


14

尝试以下查询:

db.student.find({}, {roll: 1, _id: 0});

如果你使用控制台,可以添加pretty()函数使输出更易读。

db.student.find({}, {roll: 1, _id: 0}).pretty();

希望这可以帮到你!


2
pretty() 只有在通过 shell 执行时才有用,而在脚本中则无效。 - Dinakar

11

仅供教育目的,您还可以使用以下任何一种方式来完成:

1.

    var query = {"roll": {$gt: 70};
    var cursor = db.student.find(query);
    cursor.project({"roll":1, "_id":0});

2.

    var query = {"roll": {$gt: 70};
    var projection = {"roll":1, "_id":0};
    var cursor = db.student.find(query,projection);

`


8
db.<collection>.find({}, {field1: <value>, field2: <value> ...})

在你的例子中,你可以这样做:
db.students.find({}, {"roll":true, "_id":false})

投影

投影参数确定在匹配文档中返回哪些字段。投影参数采用以下格式的文档:

{ field1: <value>, field2: <value> ... }
The <value> can be any of the following:
  1. 1 or true to include the field in the return documents.

  2. 0 or false to exclude the field.

注意

关于 _id 字段,您无需显式指定 _id: 1 来返回 _id 字段。find() 方法总是返回 _id 字段,除非您指定 _id: 0 来禁止该字段。

了解更多


7

为了更好地理解,我写了一个类似的MySQL查询。

Selecting specific fields 

MongoDB : 查询语句为db.collection_name.find({},{name:true,email:true,phone:true});

MySQL : 查询语句为SELECT name,email,phone FROM table_name;

Selecting specific fields with where clause

MongoDB : 查询集合中email为'you@email.com'的文档,返回name、email和phone字段。

MySQL : 从表table_name中查询email为'you@email.com'的记录,返回name、email和phone字段。


3

这对我来说可行,

db.student.find({},{"roll":1})

在第一个大括号中,where子句没有条件。在接下来的大括号中: 列出了需要在结果中显示的投影字段名称列表,并且1表示特定字段是查询结果的一部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接