比较查询操作符
$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"
}
}