比较查询操作符

$gt:匹配字段值大于指定值的文档

$gte:匹配字段值大于等于指定值的文档

$lt:匹配字段值小于指定值的文档

$lte:匹配字段值小于等于指定值的文档

db.human.find({"born_time":{"$gte":ISODate("2000-07-01T00:00:00Z"),"$lte": ISODate("2019-10-09T08:38:38Z")},"gender":1} ).pretty()

$eq:匹配字段值等于指定值的文档

$ne:匹配字段值不等于指定值的文档,包括没有这个字段的文档

>db.c1.find()
{"_id":ObjectId("4fb4af85afa87dc1bed94330"),"age":7,"length_1":30}
{"_id":ObjectId("4fb4af89afa87dc1bed94331"),"age":8,"length_1":30}
{"_id":ObjectId("4fb4af8cafa87dc1bed94332"),"age":6,"length_1":30}

>db.c1.find({age:{$eq:7}})
{"_id":ObjectId("4fb4af85afa87dc1bed94330"),"age":7,"length_1":30}

>db.c1.find({age:{$ne:7}})
{"_id":ObjectId("4fb4af89afa87dc1bed94331"),"age":8,"length_1":30}
{"_id":ObjectId("4fb4af8cafa87dc1bed94332"),"age":6,"length_1":30}

$in :匹配字段值等于指定数组中的任何值

$nin :字段值不在指定数组或者不存在

>db.c1.find()
{"_id":ObjectId("4fb4af85afa87dc1bed94330"),"age":7,"length_1":30}
{"_id":ObjectId("4fb4af89afa87dc1bed94331"),"age":8,"length_1":30}
{"_id":ObjectId("4fb4af8cafa87dc1bed94332"),"age":6,"length_1":30}

>db.c1.find({age:{$in:[7,8]}})
{"_id":ObjectId("4fb4af85afa87dc1bed94330"),"age":7,"length_1":30}
{"_id":ObjectId("4fb4af89afa87dc1bed94331"),"age":8,"length_1":30}

>db.c1.find({age:{$nin:[7,8]}})
{"_id":ObjectId("4fb4af8cafa87dc1bed94332"),"age":6,"length_1":30}

逻辑查询操作符

$or :文档至少满足其中的一个表达式

#下实例中,我们演示了查询键 by 值为 菜鸟教程 或键 title 值为 MongoDB 教程 的文档。
>db.col.find({$or:[{"by":"菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()

$nor:异或 逻辑或原理取反

> db.test1.find().pretty()
{
    "_id" : ObjectId("58c8dc54ef9b994487420f29"),
    "name" : "zhangsan",
    "age" : 19,
    "qty" : 10
}
{
    "_id" : ObjectId("58c8dc54ef9b994487420f2a"),
    "name" : "lisi",
    "age" : 29
}
{
    "_id" : ObjectId("58c8dc54ef9b994487420f2b"),
    "name" : "xiaoming",
    "age" : 18
}
{ 
	"_id" : ObjectId("58c9e4b80c4d4cf6f4563b26"), 
	"name" : "xiaohong"
}

> db.test1.find({"$nor": [{"age": {"$gt": 20}}, {"qty": 10}]})
{ "_id" : ObjectId("58c8dc54ef9b994487420f2b"), "name" : "xiaoming", "age" : 18, "score" : [ 20, 40 ] }
{ "_id" : ObjectId("58c9e4b80c4d4cf6f4563b26"), "name" : "xiaohong" }

$not :字段值不匹配表达式或者字段值不存在

执行一个逻辑not操作在指定的表达式并查询到不匹配表达式的文档,以及不包括字段的文档;

#此查询将会查询inventory集合中的文档,条件如下:price字段小于等于1.99或者price不存在。
db.inventory.find( { price: { $not: { $gt: 1.99 } } } )

元查询操作符

$type:匹配字段值为指定数据类型的文档

Type

Number

备注

Double

1

String

2

Object

3

Array

4

Binary data

5

Undefined

6

已废弃

Object id

7

Boolean

8

Date

9

Null

10

Regular Expression

11

JavaScript

13

Symbol

14

JavaScript (with scope)

15

32-bit integer

16

Timestamp

17

64-bit integer

18

Min key

255

Query with -1.

Max key

127

db.inventory.insertMany([
   { _id: 1, item: null },
   { _id: 2 }
])

下面的语句会查询到所有的两条记录
db.inventory.find( { item: null } )

下面的语句会查询到 { _id: 1, item: null }
db.inventory.find( { item : { $type: 10 } } )

$exists:< boolean> 等于true时,字段存在,包括字段值为null的文档

#{item: {$exists: false}查询匹配不包含item字段的文档:
db.inventory.find( { item : { $exists: false } } )
该查询仅返回不包含item字段的文档。

评价查询操作符

$mod :匹配字段值被除有指定的余数的文档

>db.c1.find()
{"_id":ObjectId("4fb4af85afa87dc1bed94330"),"age":7,"length_1":30}
{"_id":ObjectId("4fb4af89afa87dc1bed94331"),"age":8,"length_1":30}
{"_id":ObjectId("4fb4af8cafa87dc1bed94332"),"age":6,"length_1":30}

查询age取模6等于1的数据,如下面的代码所示:
>db.c1.find({age:{$mod:[6,1]}})
{"_id":ObjectId("4fb4af85afa87dc1bed94330"),"age":7,"length_1":30}

$regex :正则表达式可以匹配到的文档

>db.products.find({})
{ "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
{ "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }
{ "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }

演示忽略大小写正则表达式匹配:
如下的例子演示了一个试用选项i忽略文档中sku字段的大小写匹配并且以ABC开头;
>db.products.find( { sku: { $regex: /^ABC/i } } )
{ "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }

$text :针对创建了全文索引的字段进行文本搜索

例如,您可以使用以下查询从列表“ coffee”,“ shop”和“ java”中查找包含任何术语的所有商店:
>db.stores.find( { $text: { $search: "java coffee shop" } } )

例如,以下将查找包含“咖啡店”的所有文档:
>db.stores.find( { $text: { $search: "\"coffee shop\"" } } )

例如,要查找所有包含“ java”或“ shop”但不包含“ coffee”的商店,请使用以下命令:
>db.stores.find( { $text: { $search: "java shop -coffee" } } )

$where :可以通过js表达式或js函数来查询文档

数组查找操作符

$all :字段值是包含所有指定元素的数组的文档

此操作符跟SQL语法的in类似,不同的是in只需要匹配括号内的某一个值,而$all必须满足括号内的所有值,如下面的代码所示:

>db.users.find({age:{$all:[6,8]}});
上例可以查询出以下文档:
{name:'David',age:26,age:[6,8,9]}

但查询不出以下这条文档:
{name:'David',age:26,age:[6,7,9]}

$size:匹配数组字段元素个数等于指定数量的文档

此操作符用于统计数组中的元素个数。例如,对于记录:
{name:'David',age:26,favorite_number:[6,7,9]}

它匹配以下查询:
db.users.find({favorite_number:{$size:3}})

但不匹配以下查询:
db.users.find({favorite_number:{$size:2}})

$elemMatch:数组字段至少一个元素满足所有指定查询条件的文档

使用$elemMatch运算符可在数组的元素上指定多个条件,以使至少一个数组元素满足所有指定的条件。

以下示例查询在dim_cm数组中包含至少一个同时大于($gt)22和小于($lt)30的元素的文档:
db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )

$slice (projection):控制指定数组字段返回元素个数

假设一个文档的内嵌数组 arr 长度为10,其中数据 分别是 1-10 :
{
    _id:1000,
    arr : {
        1,2,3,4,5,6,7,8,9,10
    }
}
现在来说明 $slice 用法:

正常用法和 limit 分页查询 区别不大 如

db.col.find( {_id:1000},
    {
        "arr":{
            $slice : [0,5]
         } 
    }
)
结果为 1,2,3,4,5

下面看看 倒序取值

db.col.find( {_id:1000},
    {
        "arr":{
            $slice : [-1,5]
         } 
    }
)
结果为 10

db.col.find( {_id:1000},
    {
        "arr":{
            $slice : [-5,5]
         } 
    }
)
结果为 6 7 8 9 10

$:指定数组的第一个元素

项目数组值
收集学生包含以下文档:
{ "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 90 ] }
{ "_id" : 2, "semester" : 1, "grades" : [ 90, 88, 92 ] }
{ "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] }
{ "_id" : 4, "semester" : 2, "grades" : [ 79, 85, 80 ] }
{ "_id" : 5, "semester" : 2, "grades" : [ 88, 88, 92 ] }
{ "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96 ] }

在下面的查询中,投影{“grades.$”:1}仅返回grades字段中大于或等于85的第一个元素。
db.students.find( { semester: 1, grades: { $gte: 85 } },
                  { "grades.$": 1 } )

返回结果如下:
{ "_id" : 1, "grades" : [ 87 ] }
{ "_id" : 2, "grades" : [ 90 ] }
{ "_id" : 3, "grades" : [ 85 ] }

尽管数组字段等级可能包含多个大于或等于85的元素,但是$投影运算符仅返回数组中的第一个匹配元素。

数组更新操作符

$addToSet:数组字段增加一个值,如果数组里已经存在,则不会加入(避免重复)

例如,将userid=3的记录的name字段里追加一个别名(“N1”、“N2”)。先展示当前数据,如下面的代码所示:

>db.t3.find()
{"_id":ObjectId("4fe680228414d282f712fae7"),"userid":3,"name":["wangwenlong"]}

可以看到当前别名只有1个"wangwenlong",然后将(“N1”、“N2”)名字加入到name字段数据组里,并作为一个单独的对象,如下面的代码所示:

>db.t3.update({"userid":3},{$addToSet:{"name":["N1","N2"]}})
>db.t3.find()
{"_id":ObjectId("4fe680228414d282f712fae7"),
"name":["wangwenlong",["N1","N2"]],"userid":3}

可以看到,更新后别名里又多了1个对象,这个对象里面包含2个数据,分别是"N1"和"N2"。

$pop:删除数组字段中的第一个或最后一个元素

删除第一个值:
{$pop:{field:-1}}
删除最后一个值:
{$pop:{field:1}}
注意 此操作符只能删除一个值,也就是说只能用1或-1,而不能用2或-2来删除两条。

例如,展示当前数据,如下面的代码所示:

>db.t3.find()
{"_id":ObjectId("4fe680228414d282f712fae7"),
"name":["N1","N2","N3"],"userid":3}

接下来删除第一个值,如下面的代码所示:

>db.t3.update({"userid":3},{$pop:{"name":-1}})
>db.t3.find()
{"_id":ObjectId("4fe680228414d282f712fae7"),
"name":["N2","N3"],"userid":3}

第一个值"N1"已经被删除了,接下来删除最后一个值,如下面的代码所示:

>db.t3.update({"userid":3},{$pop:{"name":1}})
>db.t3.find()
{"_id":ObjectId("4fe680228414d282f712fae7"),"name":["N2"],"userid":3}

最后一个值"N3"已经被删除了。

$pull :符合条件的值将被删除

例如,先展示当前数据,如下面的代码所示:
>db.t3.find()
{"_id":ObjectId("4fe686288414d282f712fae8"),
"userid":3,"name":["N1","N2","N3"]}

要将name中等于"N2"的值删除,如下面的代码所示:
>db.t3.update({"userid":3},{$pull:{"name":"N2"}})
>
>db.t3.find()
{"_id":ObjectId("4fe686288414d282f712fae8"),
"name":["N1","N3"],"userid":3}

$pullAll :删除数组字段中所有指定值,如果指定值为数组,则删除匹配数组内的元素

用法同$pull一样,可以一次删除数组内的多个值。

例如,先展示当前数据,如下面的代码所示:
>db.t3.find()
{"_id":ObjectId("4fe686288414d282f712fae8"),
"name":["N1","N3"],"userid":3}

要将name中等于"N1"和"N3"的值删除,如下面的代码所示:
>db.t3.update({"userid":3},{$pullAll:{"name":["N1","N3"]}})

>db.t3.find()
{"_id":ObjectId("4fe686288414d282f712fae8"),"name":[],"userid":3}
可以看到"N1"和"N3"已经被删除了。

$push :向数组中追加值

例如,将userid=3的数据的name字段里追加一个别名"Bruce"。先展示当前数据,如下面的代码所示:
>db.t3.find()
{"_id":ObjectId("4fe67b008414d282f712fae6"),"userid":3,"name":["wangwenlong","wwl"]}

可以看到当前别名有2个,分别是"wangwenlong"和"wwl",接下来将Bruce的名字加入到name字段数据组里,如下面的代码所示:
>db.t3.update({"userid":3},{$push:{"name":"Bruce"}})

>db.t3.find()
{"_id":ObjectId("4fe67b008414d282f712fae6"),
"name":["wangwenlong","wwl","Bruce"],"userid":3}
可以看到更新后当前别名里又多了一个"Bruce"。

$pushAll :向数组中追加多个指定值

用法同 $ push一样,只是$pushAll一次可以追加多个值到一个数组字段内。

例如,将userid=3的数据的name字段里追加别名"N1"和"N2"。先展示当前数据,如下面的代码所示:
>db.t3.find()
{"_id":ObjectId("4fe67b008414d282f712fae6"),
"userid":3,"name":["wangwenlong"]}

可以看到当前别名有1个,是"wangwenlong",接下来将"N1"和"N2"名字加入到name字段数据组里,如下面的代码所示:
>db.t3.update({"userid":3},{$pushAll:{"name":["N1","N2"]}})

>db.t3.find()
{"_id":ObjectId("4fe67b008414d282f712fae6"),
"name":["wangwenlong","N1","N2"],"userid":3}
可以看到更新后当前别名里又多了2个,分别是"N1"和"N2"。

$each:用于 $addToSet添加多个值到数组中

你可以使用$ addToSet操作符和$ each修饰符配合使用,$ each修饰符允许$addToSet操作符添加多个元素到数组字段中。

集合inventory有如下文档:

{ _id: 2, item: "cable", tags: [ "electronics", "supplies" ] }

如下的操作使用$addToSet操作符和$each修饰符添加多个元素到tags数组字段中:
db.inventory.update(
   { _id: 2 },
   { $addToSet: { tags: { $each: [ "camera", "electronics", "accessories" ] } } }
 )

上面的操作只会将"camera"和"accessories"元素添加到tags数组字段中,由于"electronics"元素已经存在于数组中了。

{
  _id: 2,
  item: "cable",
  tags: [ "electronics", "supplies", "camera", "accessories" ]
}

字段更新操作符

$inc:给一个字段增加指定值

例如,将wangwenlong的年龄增加5岁。先展示当前年龄,如下面的代码所示:

>db.t3.find()
{"_id":ObjectId("4fe676348414d282f712fae4"),"name":"wangwenlong","age":30}
可以看到当前年龄是30岁,接下来将"age"增加5,如下面的代码所示:

>db.t3.update({name:"wangwenlong"},{$inc:{age:5}})
>db.t3.find()
{"_id":ObjectId("4fe676348414d282f712fae4"),"name":"wangwenlong","age":35}
>
通过结果看到,更新后年龄从30变成了35。

$setOnInsert :upsert为true时,有插入文档操作时插入指定字段值

如果update的更新参数upsert:true,也就是如果要更新的文档不存在的话会插入一条新的记录,$setOnInsert操作符会将指定的值赋值给指定的字段,如果要更新的文档存在那么$setOnInsert操作符不做任何处理;

你可以指定upsert参数在db.collection.update()和db.collection.findAndModify()方法中;

db.products.update(
  { _id: 1 },
  {
     $set: { item: "apple" },
     $setOnInsert: { defaultQty: 100 }
  },
  { upsert: true }
)

如果指定的集合文档不存在将会创建一个_id为1,其它的值为$set操作符和$setOnInsert操作符指定的字段和值;
新的集合文档是:
{ "_id" : 1, "item" : "apple", "defaultQty" : 100 }

如果是用 db.collection.update()和upsert:true能够查找到指定的集合文档,Mongodb将会更新$set操作符指定的值,忽略掉$setOnInsert指定的值;

$unset :删除指定字段

例如,将wangwenlong的年龄字段删除。展示当前数据,如下面的代码所示:

>db.t3.find()
{"_id":ObjectId("4fe676348414d282f712fae4"),"name":"wangwenlong","age":40}	
可以看到当前年龄是40岁,接下来将age字段删除,如下面的代码所示:
>db.t3.update({name:"wangwenlong"},{$unset:{age:1}})

>db.t3.find()
{"_id":ObjectId("4fe676348414d282f712fae4"),"name":"wangwenlong"}

可以看到更新后年龄字段消失了。

$rename:字段重命名

例如,先展示当前数据,如下面的代码所示:
>db.t3.find()
{"_id":ObjectId("4fe686288414d282f712fae8"),"name":[],"userid":3}

要将name字段改名为"alias",如下面的代码所示:
>db.t3.update({"userid":3},{$rename:{"name":"alias"}})
>
>db.t3.find()
{"_id":ObjectId("4fe686288414d282f712fae8"),"alias":[],"userid":3}
可以看到name消失了,换成"alias",说明重命名字段成功了。

$min :指定值小于当前值则更新为指定值

$max:指定值大于当前值则更新为指定值

考虑如下的stores集合文档
{ _id: 1, highScore: 800, lowScore: 200 }

字段lowScore当前的值是200,当前值200和指定值150进行比较,最后的结果是150,因为150比200小;
db.scores.update( { _id: 1 }, { $min: { lowScore: 150 } } )

操作的结果是:
{ _id: 1, highScore: 800, lowScore: 150 }

下面的操作不会对数据有任何影响,因为指定的值250比字段的当前值大:
db.scores.update( { _id: 1 }, { $min: { lowScore: 250 } } )

文档操作的结果是:
{ _id: 1, highScore: 800, lowScore: 150 }

$currentDate :设置字段值为当前日期
$currentDate设置字段的值为当前时间,值为Date类型或者Timestamp时间戳类型,默认是Date类型

{ _id: 1, status: "a", lastModified: ISODate("2013-10-02T01:11:18.965Z") }

如下操作更新lastModified字段为当前时间,cancellation.date字段设置为当前时间戳,并且更新status字段和cancellation.reason字段。
db.users.update(
   { _id: 1 },
   {
     $currentDate: {
        lastModified: true,
        "cancellation.date": { $type: "timestamp" }
     },
     $set: {
        status: "D",
        "cancellation.reason": "user request"
     }
   }
)

更新的结果是:
{
   "_id" : 1,
   "status" : "D",
   "lastModified" : ISODate("2014-09-17T23:25:56.314Z"),
   "cancellation" : {
      "date" : Timestamp(1410996356, 1),
      "reason" : "user request"
   }
}