美文网首页
3-MongoDB 读取文档

3-MongoDB 读取文档

作者: 前端程序猿 | 来源:发表于2020-09-08 02:10 被阅读0次

一、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({});

二、匹配查询

  • 查询 namelisi 的文档

    db.department.find({ name: "lisi" });
    
  • 查询 namelisi, 且 age19 的文档

    db.department.find({ name: "lisi", age: 19 });
    
  • 查询 _id.statusleaving 的文档(复合查询)

    db.department.find({ "_id.status": "leaving" });
    

三、比较查询操作符

语法:

{ <field>: { $<operator>: <value> } }
  • $eq 相等

    查询 namelisi, 且 age19 的文档

    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> ] } }
    

    查询 namelisizhangsan 的文档

    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 小于 30name 小于 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> } ] }

查询 namelisizhangsan 的文

// db.department.find({ name: { $in: ["lisi", "zhangsan"] } });
db.department.find({ $or: [{ name: "lisi" }, { name: "zhangsan" }] });
  • $nor 不是

查询 name 不为 lisizhangsan 的文

// 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 类型为 objectIdobject 的文档

    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> ... ] } }
    

    查询 skillpythonvuemongodb 的文档

    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 将字符串视为单行,换行符作为普通字符;

    查询 nameli 开头, 忽略大小写的文档

    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()
  • 比较操作符
  • 逻辑操作符
  • 字段操作符
  • 数组操作符
  • 运算操作符
  • 游标的操作
  • 文档投射操作

相关文章

网友评论

      本文标题:3-MongoDB 读取文档

      本文链接:https://www.haomeiwen.com/subject/fxorektx.html