3-MongoDB 读取文档
一、db.collection.find() 读取文档
Selects documents in a collection or view and returns a cursor to the selected documents.
选择集合或视图中的文档,并返回所选文档的游标。
db.collection.find(query, projection)
| 参数 | 类型 | 描述 |
|---|---|---|
| query | document | (可选的)使用查询操作符指定选择筛选器。若要返回集合中的所有文档,请省略此参数或传递一个空文档({})。 |
| projection | document | (可选的) 指定要在文档中返回与查询筛选器匹配的字段。要返回匹配文档中的所有字段,请省略此参数。 |
读取所有文档
db.department.find({});
二、匹配查询
-
查询
name为lisi的文档db.department.find({ name: "lisi" }); -
查询
name为lisi, 且age为19的文档db.department.find({ name: "lisi", age: 19 }); -
查询
_id.status为leaving的文档(复合查询)db.department.find({ "_id.status": "leaving" });
三、比较查询操作符
语法:
{ <field>: { $<operator>: <value> } }
-
$eq相等查询
name为lisi, 且age为19的文档db.department.find({ name: { $eq: "lisi" }, age: { $eq: 19 } }); // or db.department.find({ name: "lisi", age: 19 }); -
$ne不相等
查询name不等于lisi的文档db.department.find({ name: { $ne: "lisi" } });查询
_id.status不等于leaving的文档db.department.find({ "_id.status": { $ne: "leaving" } }); -
$gt大于
查询age大于18的文档db.department.find({ age: { $gt: 18 } }); -
$gte大于等于 -
$lt小于
查询name按字母大小比较, 小于lisi的文档db.department.find({ name: { $lt: "lisi" } }); -
$lte小于等于 -
$in选择字段值等于指定数组中任何值的文档。
语法:{ field: { $in: [<value1>, <value2>, ... <valueN> ] } }查询
name为lisi或zhangsan的文档db.department.find({ name: { $in: ["lisi", "zhangsan"] } }); -
$nin选择字段值不等于指定数组中任何值的文档。
四、逻辑查询操作符
-
$not取反
语法:{ field: { $not: { <operator-expression> } } }查询
age不大于18的文档db.department.find({ age: { $not: { $gt: 18 } } }); -
$and且
语法:{ $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ]}查询
age大于18小于30的文档// db.department.find({ age: { $gt: 18, $lt: 30 } }); // db.department.find({ $and: [{ age: { $gt: 18, $lt: 30 } }] }); db.department.find({ $and: [{ age: { $gt: 18 } }, { age: { $lt: 30 } }] });查询
age小于30且name小于lisi的文档// db.department.find({ name: { $lt: 'lisi' }, age: { $lt: 30 } }) db.department.find({ $and: [{ name: { $lt: "lisi" } }, { age: { $lt: 30 } }], }); -
$or或
语法:
{ $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }
查询 name 为 lisi 或 zhangsan 的文
// db.department.find({ name: { $in: ["lisi", "zhangsan"] } });
db.department.find({ $or: [{ name: "lisi" }, { name: "zhangsan" }] });
-
$nor不是
查询 name 不为 lisi 或 zhangsan 的文
// db.department.find({ name: { $nin: ["lisi", "zhangsan"] } });
db.department.find({ $nor: [{ name: "lisi" }, { name: "zhangsan" }] });
五、 字段查询操作符
-
$exists匹配具有指定字段的文档
语法:{ field: { $exists: <boolean> } }查询具有
_id.status属性的文档db.department.find({ "_id.status": { $exists: true } });查询具有
_id.status属性的文档, 且值不为working的文档db.department.find({ "_id.status": { $exists: true, $ne: "working" } }); -
$type匹配字段类型为指定类型的文档
语法:具体类型
{ field: { $type: <BSON type> } }多个类型
{ field: { $type: [ <BSON type1> , <BSON type2>, ... ] } }支持的类型:
Type Number Alias Notes Double 1 “double” String 2 “string” Object 3 “object” Array 4 “array” Binary data 5 “binData” Undefined 6 “undefined” Deprecated. ObjectId 7 “objectId” Boolean 8 “bool” Date 9 “date” Null 10 “null” Regular Expression 11 “regex” DBPointer 12 “dbPointer” Deprecated. JavaScript 13 “javascript” Symbol 14 “symbol” Deprecated. JavaScript (with scope) 15 “javascriptWithScope” Deprecated in MongoDB 4.4. 32-bit integer 16 “int” Timestamp 17 “timestamp” 64-bit integer 18 “long” Decimal128 19 “decimal” New in version 3.4. Min key -1 “minKey” Max key 127 “maxKey” 查询
_id的类型为string的文档db.department.find({ _id: { $type: "string" } });查询
_id类型为objectId或object的文档db.department.find({ _id: { $type: ["objectId", "object"] } });
六、数组查询操作符
准备数据
db.department.insert([
{
name: "a",
skill: ["vue", "python", "mongodb"],
},
{
name: "b",
skill: ["vue", "nodejs", "mongodb", "ngix"],
},
{
name: "c",
skill: ["react", "nodejs", "mongodb", "docker"],
},
{
name: "d",
skill: [["django", "flask", "pycharm"]],
},
{
name: "e",
skill: [["django", "flask", "vscode", "vuex", "element-ui"]],
},
]);
-
$all匹配包含所有指定值的数组。
语法:{ <field>: { $all: [ <value1> , <value2> ... ] } }查询
skill有python、vue、mongodb的文档db.department.find({ skill: { $all: ["python", "vue", "mongodb"] } }); // db.department.find({ $and: [{ skill: 'python' }, { skill: 'vue' }, { skill: 'mongodb' }] })查询
skill有["django", "flask", "pycharm"]的文档db.department.find({ skill: [['django', 'flask', 'pycharm']] } -
$elemMatch匹配包含指定值的数组
语法:{ <field>: { $elemMatch: { <query1>, <query2>, ... } } }查询
skill中大于docker小于vue的文档db.department.find({ skill: { $elemMatch: { $gt: "docker", $lt: "vue", }, }, });查询
skill中(大于docker且 小于vue) 而且 (大于docker且 小于webpack)的文档db.department.find({ skill: { $all: [ { $elemMatch: { $gt: "docker", $lt: "vue", }, }, { $elemMatch: { $gt: "docker", $lt: "webpack", }, }, ], }, }); -
$size匹配指定大小的数组。
查询skill数组长度为3的文档db.department.find({ skill: { $size: 3, }, });
七、运算查询操作符
-
$regex选择值与指定正则表达式匹配的文档语法:
{ <field>: { $regex: /pattern/, $options: '<options>' } } { <field>: { $regex: 'pattern', $options: '<options>' } } { <field>: { $regex: /pattern/<options> } }你也可以使用正则表达式对象(如
/pattern/)来指定正则表达式{ <field>: /pattern/<options> }$options: 匹配模式-
i忽略大小写 -
m多行匹配 -
x将模式中的空白忽略 -
s将字符串视为单行,换行符作为普通字符;
查询
name以li或李开头, 忽略大小写的文档db.department.find({ name: { $regex: /(^li)|(^李)/, $options: "i" } }); db.department.find({ name: { $regex: "(^li)|(^李)", $options: "i" } }); db.department.find({ name: { $regex: /(^li)|(^李)/i } }); db.department.find({ name: /(^li)|(^李)/i }); db.department.find({ name: { $in: [/^li/, /^李/] } }); -
八、游标操作
db.collection.find()方法返回一个游标, 要访问文档,需要迭代游标。但是,如果返回的游标没有使用var关键字分配给变量,那么游标最多只显示结果中前 20 条文档
var myCursor = db.department.find({});
myCursor;
访问查询结果的第一条文档
var myCursor = db.department.find({});
myCursor[0];
遍历游标
var myCursor = db.department.find({});
while (myCursor.hasNext()) {
printjson(myCursor.next());
}
// myCursor.forEach(printjson);
默认情况下,在 10 分钟内不活动或者已经遍历完的游标将自动关闭,覆盖此行为,可以使用cursor.noCursorTimeout()方法:
var myCursor = db.department.find().noCursorTimeout();
手动关闭游标
myCursor.close();
指定返回文档的数量
var myCursor = db.department.find({});
myCursor.limit(2);
跳过指定数量的文档
var myCursor = db.department.find({});
myCursor.skip(2);
翻页时,假设每页显示 2 条文档,则第二页的数据应该为:
var myCursor = db.department.find({});
myCursor.skip(2).limit(2);
当 limit方法参数为 0 时,将返回剩下的所有文档
var myCursor = db.department.find({});
myCursor.skip(2).limit(0);
获取游标中文档的总个数
var myCursor = db.department.find({});
// 不考虑是否调用了 `limit` 或 `skip` 方法, 将返回总个数
myCursor.count();
// 如果想知道调用了 `limit` 或 `skip` 方法后返回的个数
myCursor.count(true);
如:
> var myCursor = db.department.find().noCursorTimeout();
> myCursor.limit(2)
{ "_id" : "employee1", "name" : "zhangsan", "age" : 18 }
{ "_id" : ObjectId("5f4fe031b3dbdc66cacb3b8d"), "name" : "lisi", "age" : 19 }
> myCursor.count()
19
> myCursor.count(true)
2
cursor.sort(<document>)对文档进行排序
在 sort 参数中指定要排序的字段,值为 1 或-1 分别指定升序或降序排序。
假如对游标中的文档按 age 升序, name 降序
var myCursor = db.department.find({});
myCursor.sort({ age: 1, name: -1 });
查询 age 最大的文档
db.department.find({}).sort({ age: -1 }).limit(1)[0];
链式查询时,需要注意函数的优先级
skip 的优先级大于 limit 所以下面的命令,返回相同的结果
db.department.find({}).skip(5).limit(5);
db.department.find({}).limit(5).skip(5);
sort 的优先级 大于 skip
db.department.find({}).skip(5).limit(5).sort({ age: -1 });
// db.department.find({}).sort({ age: -1 }).skip(5).limit(5);
九、文档的投射
投影参数决定在匹配的文档中返回哪些字段
投影参数采用以下形式的文档
{ <field1>: <value>, <field2>: <value> ... }
-
<field>: <1 or true>指定包含的字段 -
<field>: <0 or false>指定排除的字段
返回的文档中,只包含字段 name 和 _id
db.department.find({}, { name: 1 });
返回的文档中,只包含字段 name
db.department.find({}, { name: 1, _id: 0 });
返回的文档中,不包含字段 name
db.department.find({}, { name: 0 });
除了文档主键 _id 外,不能再投射中使用,即包含与不包含的操作
try {
db.department.find({}, { name: 0, age: 1 });
} catch (e) {
print(e);
}
运行结果:
Error: error: {
"ok" : 0,
"errmsg" : "Cannot do inclusion on field age in exclusion projection",
"code" : 31253,
"codeName" : "Location31253"
}
十、 投影操作符
-
$slice (projection)指定在查询结果中返回的数组中的元素数量语法:
db.collection.find( <query>, { <arrayField>: { $slice: <number to return> } } );或
db.collection.find( <query>, { <arrayField>: { $slice: [ <number to skip>, <number to reutrn> ] } } );返回
skill数组中的前 2 个元素db.department.find({}, { skill: { $slice: 2 } });返回
skill数组中忽略第一个元素后的 2 个元素db.department.find({}, { skill: { $slice: [1, 2] } });返回
skill数组中的最后 2 个元素db.department.find({}, { skill: { $slice: -2 } }); -
$elemMatch (projection)返回数组中满足条件的第一个元素返回
skill数组中的大于python的第一个元素
如果没有找到匹配的元素,skill字段将被忽略db.department.find({}, { skill: { $elemMatch: { $gt: "python" } } });该操作符,会忽略掉除了
_id的其他字段, 其他字段需要显示指定db.department.find( {}, { name: 1, age: 1, skill: { $elemMatch: { $gt: "python" } } } );引用查询条件中的值: 如果查询条件中有
skill数组的过滤条件,可以使用投射中使用下面的方式,调用$elemMatch操作符db.department.find({ skill: { $gt: "python" } }, { "skill.$": 1 }); // db.department.find({ skill: { $gt: 'python' } }, { skill: { $elemMatch: { $gt: 'python' } } })
十一、 总结
db.collection.find()- 比较操作符
- 逻辑操作符
- 字段操作符
- 数组操作符
- 运算操作符
- 游标的操作
- 文档投射操作