跳至主要內容

MongoDB Shell 查询

zhengcog...大约 8 分钟数据库NoSQL

一.简介

MongoDB 查询文档使用find()方法,已非结构化的方式显示所有文档

语法格式:

db.collection.find(query, projection)

参数:

  • query: 可选,使用查询操作符指定查询条件
  • projection: 可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)

对于查询的结果可以添加limits, skips, sort 等方式控制返回的结果集
缺省情况下,在mongo shell中对于未使用将结果集返回给变量的情形下,仅返回前20条记录
注:本文描述中有些地方使用到了文档的键值对,称为键和值,有些地方称为列,是一个概念

如果需要以易读的方式来展示数据,可以使用pretty()方法,语法格式如下:

db.collection_name.find().pretty()

二.实例

1. 准备数据

db.mytest.insertMany(
  [
    {
      _id: 1,
      name: "sue",
      age: 19,
      type: 1,
      status: "P",
      favorites: { artist: "Picasso", food: "pizza" },
      finished: [ 17, 3 ],
      badges: [ "blue", "black" ],
      points: [
        { points: 85, bonus: 20 },
        { points: 85, bonus: 10 }
      ]
    },
    {
      _id: 2,
      name: "bob",
      age: 42,
      type: 1,
      status: "A",
      favorites: { artist: "Miro", food: "meringue" },
      finished: [ 11, 25 ],
      badges: [ "green" ],
      points: [
        { points: 85, bonus: 20 },
        { points: 64, bonus: 12 }
      ]
    },
    {
      _id: 3,
      name: "ahn",
      age: 22,
      type: 2,
      status: "A",
      favorites: { artist: "Cassatt", food: "cake" },
      finished: [ 6 ],
      badges: [ "blue", "red" ],
      points: [
        { points: 81, bonus: 8 },
        { points: 55, bonus: 20 }
      ]
    },
    {
      _id: 4,
      name: "xi",
      age: 34,         //Author : Leshami
      type: 2,         //Blog   : http://blog.csdn.net/leshami
      status: "D",
      favorites: { artist: "Chagall", food: "chocolate" },
      finished: [ 5, 11 ],
      badges: [ "red", "black" ],
      points: [
        { points: 53, bonus: 15 },
        { points: 51, bonus: 15 }
      ]
    },
    {
      _id: 5,
      name: "xyz",
      age: 23,
      type: 2,
      status: "D",
      favorites: { artist: "Noguchi", food: "nougat" },
      finished: [ 14, 6 ],
      badges: [ "orange" ],
      points: [
        { points: 71, bonus: 20 }
      ]
    },
    {
      _id: 6,
      name: "abc",
      age: 43,
      type: 1,
      status: "A",
      favorites: { food: "pizza", artist: "Picasso" },
      finished: [ 18, 12 ],
      badges: [ "black", "blue" ],
      points: [
        { points: 78, bonus: 8 },
        { points: 57, bonus: 7 }
      ]
    }
  ]
)

2. 简单查询

// 查询所有文档
db.mytest.find() 或 db.mytest.find({})

// 查询单条记录
db.mytest.findOne()

// 指定条件查询
db.mytest.find({_id: 5}).pretty()

// 多条件查询,隐式使用$and运算符
db.mytest.find({age:19,status:"P"})

3. 使用运算符查询

// 语法格式
db.collection_name.find({ <field1: { <operator1: <value1 }, ... })

// 使用$in运算符
db.mytest.find({status: {$in: ["P","D"]}})

// 使用$and运算符
db.mytest.find( {$and: [{ status: "A", age: { $lt: 30 } } ]})
db.mytest.find( { status: "A", age: { $lt: 30 } } ) //此查询方法与上一条等价

// 使用$or运算符
db.mytest.find( { $or: [ { status: "A" }, { age: { $lt: 30 } }]})

// 多条件组合查询
db.mytest.find(
  {
    status: "A",
    $or: [ { age: { $lt: 30 } }, { type: 1 } ]
  }
)

4. 内嵌文档查询

// 等值匹配内嵌文档
db.mytest.find({favorites: {artist: "Picasso", food: "pizza"}})
// 等值匹配内嵌文档的特定键值,通过"键.成员名:值"的方式来进行
db.mytest.find( { "favorites.artist": "Picasso" } )

5. 数组查询

// 查询数组元素 此例查询数组badges中包含black的文档
db.mytest.find({badges: "black"})

// 匹配一个特定的数组元素,此例查询数组badges中第一个元素为black的文档
db.mytest.find({ "badges.0": "black" }) // 此处0表示数组的下标

// 匹配单个数组元素满足条件,此例查询数组finished至少有一个元素的值大于15且小于20的文档
db.mytest.find( { finished: { $elemMatch: { $gt: 15, $lt: 20 } } } )

// 匹配混合数组元素满足条件,此例查询数组finished中任意的一个元素大于15,且另外一个元素小于20
db.mytest.find( { finished: { $gt: 15, $lt: 20 } } )  //或者这个元素既大于15又小于20的文档

// 查询数组内嵌文档,此例查询数组points元素1内嵌文档键points的值小于等于55的文档
db.mytest.find( { 'points.0.points': { $lte: 55 } } )

// 查询数组内嵌文档,此例查询数组points内嵌文档键points的值小于等于55的文档,此处未指定数组下标
db.mytest.find( { 'points.points': { $lte: 55 } } )

// 查询数组元素至少一个内嵌文档满足所有条件的文档
// 如下,数组points内至少一个文档points键的值小于等于70,bonus键的值等于20的记录,这样的文档被返回
db.mytest.find( { points: { $elemMatch: { points: { $lte: 70 }, bonus: 20 } } } )

// 查询数组元素任意一个内嵌文档满足所有条件的文档
// 如下,数组points内嵌文档任意一个文档points的值小于等于70,且数组内另外一个文档bonus值等于20
// 或者数组内某个内嵌文档points的值小于等于70,bonus的值等于20,这2种情形会被返回
db.mytest.find( { "points.points": { $lte: 70 }, "points.bonus": 20 } )

6. 限制查询返回的结果集

{ field1: <value>, field2: <value> ... }
1 or true  显示该字段
0 or false 不显示该字段

6.1 限制返回的列

// 查询结果中显示字段name及status,缺省情况下,文档的_id列会被返回
db.mytest.find( { status: "A" }, { name: 1, status: 1 } )

// 查询结果中显示字段name及status,且不显示_id列
db.mytest.find( { status: "A" }, { name: 1, status: 1, _id: 0 } )

// 返回查询中未列出的全部列名
db.mytest.find( { status: "A" }, { favorites: 0, points: 0 ,badges:0})

// 返回内嵌文档指定的列名,相反地,如果不显示内嵌文档的某个列,将在置0即可
db.mytest.find(
  { status: "A" },
  { name: 1, status: 1, "favorites.food": 1 }
)

// 返回数组内内嵌文档的指定列,如下查询为数组points内嵌文档bonus列
db.mytest.find( { status: "A" },{ name: 1,"points.bonus": 1 } )

// 下面的查询使用了$slice操作符,这将仅仅返回符合status为A,且显示数组中的最后一个元素
db.mytest.find( { status: "A" }, { name: 1, status: 1, points: { $slice: -1 } } )

6.2 限制返回的行

如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。可以使用skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。

语法格式:

db.collection_name.find().limit(NUMBER).skip(NUMBER)

举例:

// 实现翻页功能,每页1条数据
// 第一页
db.mytest.find().limit(1).skip(0)

// 第二页
db.mytest.find().limit(1).skip(1)

// 第三页
db.mytest.find().limit(1).skip(2)

6.3 查询NULL值或不存在的件

// 插入文档
db.mytest.insertMany(
  [
    { "_id" : 900, "name" : null },
    { "_id" : 901 },
    { "_id" : 902,"name" : "zhengcog" ,"blog" : "https://www.zhengcog.com"}  
  ]
)

// 查询name字段为null的文档,注,以下查询中,不存在name列的文档_id:901的也被返回
db.mytest.find( { name: null } )

// 通过$type方式返回name为null的文档,此时_id:901未返回
db.mytest.find( { name : { $type: 10 } } )

// 通过$exists返回name字段不存在的文档
db.mytest.find( { name : { $exists: false } } )

7. 排序

MongoDB 使用sort()方法排序,可以指定排序的字段并使用1和-1指定排序方式,1为升序 -1为降序

语法格式:

db.collection_name.find().sort({KEY: 1})

举例:

// 按照age升序
db.mytest.find().sort({age: 1})

// 按照age降序
db.mytest.find().sort({age: -1})

// 多字段排序,如果第一个字段相同,则按照第二个字段排序
// 此例按照age升序、type降序排序
db.mytest.find().sort({age:1,type:-1})

// 按照日期排序,将数据增加createdDate字段
db.mytest.updateMany({},{$set: {createdDate: ISODate("2023-06-30T11:00:00.000Z")}})
// 按照日期降序排序
db.mytest.find().sort({createdDate: -1})

// 按照嵌入字段排序,此例按照favorites字段中的artist升序排序
db.mytest.find().sort({"favorites.artist": 1})

8. 聚合查询

聚合操作主要用于处理数据并返回计算结果。聚合操作将来自多个文档的值组合在一起,按条件分组后,再进行一系列操作(如求和、平均值、最大值、最小值)以返回单个结果。

MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似 SQL 语句中的 count(*)

语法格式:

db.collection_name.aggregate(aggregate_operation)

与mysql聚合类比

SQL 操作/函数mongodb聚合操作
where$match
group by$group
having$match
select$project
order by$sort
limit$limit
sum()$sum
count()$sum
join$lookup

8.2 测试数据

db.users.insertMany(
  [
    {
      _id: 1,
      name: "sue",
      age: 19,
      type: 1,
      status: "P",
      amount: 10,
      favorites: { artist: "Picasso", food: "pizza" },
      finished: [ 17, 3 ],
      badges: [ "blue", "black" ],
      points: [
        { points: 85, bonus: 20 },
        { points: 85, bonus: 10 }
      ]
    },
    {
      _id: 2,
      name: "bob",
      age: 42,
      type: 1,
      status: "A",
      amount: 20,
      favorites: { artist: "Miro", food: "meringue" },
      finished: [ 11, 25 ],
      badges: [ "green" ],
      points: [
        { points: 85, bonus: 20 },
        { points: 64, bonus: 12 }
      ]
    },
    {
      _id: 3,
      name: "ahn",
      age: 22,
      type: 2,
      status: "A",
      amount: 30,
      favorites: { artist: "Cassatt", food: "cake" },
      finished: [ 6 ],
      badges: [ "blue", "red" ],
      points: [
        { points: 81, bonus: 8 },
        { points: 55, bonus: 20 }
      ]
    },
    {
      _id: 4,
      name: "xi",
      age: 34,         //Author : Leshami
      type: 2,         //Blog   : http://blog.csdn.net/leshami
      status: "D",
      amount: 40,
      favorites: { artist: "Chagall", food: "chocolate" },
      finished: [ 5, 11 ],
      badges: [ "red", "black" ],
      points: [
        { points: 53, bonus: 15 },
        { points: 51, bonus: 15 }
      ]
    },
    {
      _id: 5,
      name: "xyz",
      age: 23,
      type: 2,
      status: "D",
      amount: 50,
      favorites: { artist: "Noguchi", food: "nougat" },
      finished: [ 14, 6 ],
      badges: [ "orange" ],
      points: [
        { points: 71, bonus: 20 }
      ]
    },
    {
      _id: 6,
      name: "abc",
      age: 43,
      type: 1,
      status: "A",
      amount: 60,
      favorites: { food: "pizza", artist: "Picasso" },
      finished: [ 18, 12 ],
      badges: [ "black", "blue" ],
      points: [
        { points: 78, bonus: 8 },
        { points: 57, bonus: 7 }
      ]
    }
  ]
)

8.3 示例

查询集合中所有文档总数

db.users.countDocuments()
6 // 输出结果

查询集合中所有文档总数

db.users.aggregate([
    {
        "$group": {
            "_id": null,
            "count": {// 这里count自定义,相当于mysql的select count(*) as tables
                "$sum": 1
            }
        }
    },
    {
        "$project": {// 返回不显示_id字段
            "_id": 0
        }
    }
])
[ { count: 6 } ] // 输出结果

查询amount是20以上的文档数量

db.users.aggregate([
  {
    "$match": {
      "amount": {"$gt": 20}
    }
  },
  {
    "$count": "count"
  }
])

按照status分组,统计每个分组下的总人数、amount平均数以及每个分组的amount的总数

db.users.aggregate([
  {
    "$group": {
      "_id": "$status",
      "totalAmount": { // 每个分组amount的总数
        "$sum": "$amount"
      },
      "avgAmount": {
        "$avg":"$amount" // 每个分组amount的平均数
      },
      "count": {"$sum":1} // 每个分组总人数
    }
  }
])

查找不重复的所有status的值

db.users.aggregate([
  {
    "$group": {"_id": "$status"}
  }
])

三. 附录:$type操作符

$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果

使用类型如下:

类型数字备注
Double1
String2
Object3
Array4
Binary data5
Undefined6已废弃。
Object id7
Boolean8
Date9
Null10
Regular Expression11
JavaScript13
Symbol14
JavaScript (with scope)15
32-bit integer16
Timestamp17
64-bit integer18
Min key255Query with -1.
Max key127
上次编辑于:
贡献者: Hyman
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.5