主要是說(shuō)明mongodb的數(shù)據(jù)查詢方法,本次不使用mongo shell來(lái)操作,使用圖形化操作軟件Robo來(lái)執(zhí)行mongo shell命令~~~
Mongo 查詢
1. 集合查詢方法 find()
1.1 語(yǔ)法
# 查詢集合中文檔并返回結(jié)果為游標(biāo)的文檔集合。
# -------------------------------------
# 方法一
db.getCollection(cname).find(query, projection)
# 方法二
db.cname.find(query, projection)
參數(shù)說(shuō)明
參數(shù) | 類型 | 描述 |
---|---|---|
cname | 文檔集合 | 必填 類似mysql中的數(shù)據(jù)庫(kù) |
query | 文檔 | 可選 使用查詢操作符指定查詢條件 |
projection | 文檔 | 可選 使用投影操作符指定返回的鍵 查詢時(shí)返回文檔中所有鍵值, 只需省略該參數(shù)即可(默認(rèn)省略). |
1.2 返回值
匹配查詢條件的文檔集合的游標(biāo). 結(jié)果如圖,類似于{"_id" : ObjectId("59673da41c53063954519019"),}。如果在projection指定投影參數(shù),查詢出的文檔返回指定的鍵 ,包括"_id"鍵也可以從集合中移除掉.
2. query查詢條件
2.1 默認(rèn)值:{}
會(huì)查詢匹配集合中的全部?jī)?nèi)容。,如同SQL中"SELECT * FROM Table_name"語(yǔ)句。
# 將返回集合中所有文檔
# ------------------
# 方法一
db.getCollection(cname).find()
# 方法二
db.getCollection(cname).find({})
2.2 鍵值對(duì) {key:value}
執(zhí)行了條件篩選,就如同SQL中"SELECT * FROM Table_name where key = value"語(yǔ)句。
下面查詢操作將返回raw_data_single集合中host鍵值為g61的文檔集合,結(jié)果如圖
db.getCollection('raw_data_single').find({"host":"g61"})
鍵值對(duì)AND {key1:value1,key2:value2}
則相當(dāng)于查詢AND組合條件,“條件1 AND條件2 AND…AND 條件N"
下面查詢操作將返回raw_data_single集合中host鍵值為g61并且ip鍵值為59的文檔集合,結(jié)果如圖
# mongo db
db.getCollection('raw_data_single').find({"host":"g61","ip":"59"})
3. projection指定返回的鍵
3.1 默認(rèn)值
查詢操作默認(rèn)返回查詢文檔中所有鍵值。像SQL中我們可以指定*查詢返回字段一樣。從未指定projection的查詢中,我們可以看到所有的字段都被返回了。通過(guò) true 和 false 來(lái)制定是否顯示鍵值。
# 指定顯示host,但是_id會(huì)默認(rèn)顯示,可以用 1 和 0 代替 ture 和 false
db.getCollection('raw_data_single').find({"host":"g61"},{"host":1})
結(jié)果如下:
# 指定去掉_id的鍵值
db.getCollection('raw_data_single').find({"host":"g61"},{"host":true,"_id":false})
結(jié)果如下:
4 內(nèi)嵌文檔查詢
4.1 完全匹配查詢
db.raw_data_single.find({"host":"g61","facts":{"mtu_eth0":1500,"mtu_eth1":1500}})
結(jié)果:沒(méi)有,由于facts里面的數(shù)據(jù)過(guò)多我刪掉了部分才能寫(xiě)完全匹配,結(jié)果如下
注意:在沒(méi)有刪除其他facts數(shù)據(jù)前是無(wú)法查詢到數(shù)據(jù)的,完全匹配!!!
4.2 點(diǎn)的方式查詢
db.raw_data_single.find({"host":"g61","facts.mtu_eth0":1500})
結(jié)果如下:
4.3 $elemMatch操作符(搜索對(duì)象為數(shù)組)
使用點(diǎn)的方式對(duì)數(shù)組進(jìn)行搜索,會(huì)對(duì)數(shù)組里面所有的內(nèi)容逐一對(duì)比,只要有一個(gè)值符合條件都返回文檔的內(nèi)容。集合blogs有如下文檔:
{
"_id" : ObjectId("596c1eea3df4768f4e992dd6"),
"comment" : [
{
"author" : "zhangsan",
"score" : 3,
"comment" : "shafa!"
},
{
"author" : "lisi",
"score" : 5,
"comment" : "lzsb!"
}
]
}
不符合預(yù)期的搜索,
db.blogs.find({"comment.author":"zhangsan", "comment.score":{"$gte":4}});
使用$elemMatch操作符進(jìn)行搜索:
# 張三分?jǐn)?shù)大于4,搜索結(jié)果為空
db.blogs.find({"comment":{"$elemMatch":{"author":"zhangsan","score":{"$gt":4}}}});
# 張三分?jǐn)?shù)大于2,搜索出id為596c1eea3df4768f4e992dd6的文檔
db.blogs.find({"comment":{"$elemMatch":{"author":"zhangsan","score":{"$gt":2}}}});
5 查詢操作符
5.1 "$gt" 、"$gte"、 "$lt"、 "$lte" - 比較操作符
比較操作符"$gt" 、"$gte"、 "$lt"、 "$lte"(分別對(duì)應(yīng)">"、 ">=" 、"<" 、"<=")
#查詢年齡為16-18歲(包含16但不含18)的用戶:
db.user.find( { age: { $gte: 16 ,$lt:18} }
#我們可以使用"$ne"來(lái)進(jìn)行"不相等"操作。例如查詢年齡不為18歲的用戶:
db.user.find( { age: {$ne:18} }
#要査找在1990年1月1日出生的用戶:
start = new Date("1990/01/01")
db.users.find({"birthday" : {"$lt" : start}})
5.2 "$in" - 判斷鍵值是否為null
如何檢索出sex鍵值為null的文檔,我們使用"in"、"where"操作符
"$in"判斷鍵值是否為null
"$exists"判定集合中文檔是否包含該鍵
測(cè)試文檔如下:
{
"_id" : ObjectId("596c5e351109af0230579527"),
"name" : "xiaoming",
"age" : 20,
"sex" : "male"
}
{
"_id" : ObjectId("596c5e351109af0230579529"),
"name" : "xiaohong",
"age" : 22
}
{
"_id" : ObjectId("596c5e351109af023057952b"),
"name" : "lilei",
"age" : 24,
"sex" : null
}
# 返回文檔中存在sex鍵,且值為null的文檔
# ----------------------------------
# 方法一,建議使用
db.users.find({sex:{$in:[null],$exists:true}})
# 結(jié)果為:
"_id" : ObjectId("596c5e351109af023057952b")
# 方法二,慎用:因?yàn)閚ull不僅僅匹配自身,而且匹配鍵“不存在的”文檔!
db.users.find({sex:null})
# 結(jié)果為:
"_id" : ObjectId("596c5e351109af0230579529")
"_id" : ObjectId("596c5e351109af023057952b")
5.3 "$all" - 數(shù)組精確匹配
$all: 匹配那些指定鍵的鍵值中包含數(shù)組,而且該數(shù)組包含條件指定數(shù)組的所有元素的文檔,數(shù)組中元素順序不影響查詢結(jié)果。
語(yǔ)法: {field: {\$all: [value, value1, ...]}
測(cè)試文檔如下:
{
"_id" : ObjectId("596c605b1109af02305795b9"),
"name" : "t1",
"amount" : 50,
"tags" : [ "school", "book", "bag", "headphone", "appliances"]
}
{
"_id" : ObjectId("596c605b1109af02305795bb"),
"name" : "t2",
"amount" : 50,
"tags" : ["appliances", "school", "book"]
}
{
"_id" : ObjectId("596c605b1109af02305795bd"),
"name" : "t3",
"amount" : 58,
"tags" : ["bag", "school", "book"]
}
數(shù)組中使用
#查詢出在集合inventory中 tags鍵值包含數(shù)組,且該數(shù)組中包含appliances、school、 book元素的所有文檔:
db.inventory.find({tags:{$all:["appliances","school","book"]}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
非數(shù)組使用
文檔中鍵值類型不是數(shù)組,也可以使用$all操作符進(jìn)行查詢操作
# 查詢結(jié)果是相同的,匹配amount鍵值等于50的文檔
db.inventory.find({amount: {$all:[50]}})
db.inventory.find({amount: 50})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795b9")
指定數(shù)組位置的元素
則需使用key.index語(yǔ)法指定下標(biāo),例如下面查詢出tags鍵值數(shù)組中第2個(gè)元素為"school"的文檔:
# 數(shù)組下標(biāo)都是從0開(kāi)始的,所以查詢結(jié)果返回?cái)?shù)組中第2個(gè)元素為"school"的文檔:
db.inventory.find({"tags.1":"school"})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795bd")
5.4 "$size" - 指定長(zhǎng)度的數(shù)組
固定長(zhǎng)度
語(yǔ)法:{field: {$size: value}}
測(cè)試使用5.3的文檔,具體測(cè)試如下:
查詢集合中tags鍵值包含有3個(gè)元素的數(shù)組的所有文檔:
db.inventory.find({tags:{$size:3}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795bd")
非固定長(zhǎng)度(通過(guò)計(jì)數(shù)器的方法解決),具體例子略
size必須制定一個(gè)定值,不能接受一個(gè)范圍值,不能與其他查詢子句組合(比如"gt")。
但有時(shí)查詢需求就是需要一個(gè)長(zhǎng)度范圍,這種情況創(chuàng)建一個(gè)計(jì)數(shù)器字段,當(dāng)你增加元素的同時(shí)增加計(jì)數(shù)器字段值。
# 每一次向指定數(shù)組添加元素的時(shí)候,"count"鍵值增加1(充當(dāng)計(jì)數(shù)功能)
db.collection.update({$push :{field:value}, $inc:{count: 1}})
# 比較count鍵值實(shí)現(xiàn)范圍查詢
db.collection.find({count : {$gt:2}})
5.5 "$in"、"$nin" - [匹配鍵值等于、匹配鍵不等于或者不存在]指定數(shù)組中任意值的文檔
語(yǔ)法:{field:{$in:[<value1>,<value2>,...<valueN>]}}
測(cè)試使用5.3的文檔,具體測(cè)試如下:
# 查詢出amount鍵值為16或者50的文檔:
db.inventory.find({amount: {$in: [16, 50]}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
# 查詢出amount鍵值不為16或者50的文檔
db.inventory.find({amount: {$nin: [16, 50]}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795bd")
# 查詢出qty鍵值不為16或50的文檔,由于文檔中都不存在鍵qty,所以返回所有文檔
db.inventory.find({qty:{$nin:[16,50]}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795bd")
# 查詢結(jié)果是相同的,匹配amount鍵值等于50的文檔,只有一個(gè)值與all的操作是一樣的
db.inventory.find({amount: {$in: [50]}})
db.inventory.find({amount: 50})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795b9")
5.6 "$and" - 選擇出滿足該數(shù)組中所有表達(dá)式的文檔
指定一個(gè)至少包含兩個(gè)表達(dá)式的數(shù)組,選擇出滿足該數(shù)組中所有表達(dá)式的文檔。
語(yǔ)法:{$and:[{<expression1>},{<expression2>},...,{<expressionN>}]}
注意:$and操作符使用短路操作,若第一個(gè)表達(dá)式的值為“false”,余下的表達(dá)式將不會(huì)執(zhí)行。
測(cè)試使用5.3的文檔,具體測(cè)試如下:
#查詢name鍵值為“t1”,amount鍵值小于51的文檔:
db.inventory.find({$and: [{name: "t1"},{amount: {$lt: 51}}]})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
#對(duì)于下面使用逗號(hào)分隔符的表達(dá)式列表,MongoDB會(huì)提供一個(gè)隱式的$and操作:
db.inventory.find({name:"t1",amount:{$lt: 50}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
5.7 "$nor" - 選擇出都不滿足該數(shù)組中所有表達(dá)式的文檔
指定一個(gè)至少包含兩個(gè)表達(dá)式的數(shù)組,選擇出都不滿足該數(shù)組中所有表達(dá)式的文檔。
語(yǔ)法:{$nor:[{<expression1>},{<expression2>},...,{<expressionN>}]}
測(cè)試使用5.3的文檔,具體測(cè)試如下:
# 查詢name鍵值不為“t1”,amount鍵值不小于50的文檔:
db.inventory.find({$nor: [{name: "t1"},{qty: {$lt: 50}}]})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795bd")
# 若是文檔中不存在表達(dá)式中指定的鍵,表達(dá)式值為false; false nor false 等于 true,所以查詢結(jié)果返回集合中所有文檔:
db.inventory.find({$nor: [{sale: true},{qty: {$lt: 50}}]})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795bd")
5.8 "$not" - 選擇出不能匹配表達(dá)式的文檔
執(zhí)行邏輯NOT運(yùn)算,選擇出不能匹配表達(dá)式的文檔 ,包括沒(méi)有指定鍵的文檔。
$not操作符不能獨(dú)立使用,必須跟其他操作一起使用(除$regex)。
語(yǔ)法:{field:{$not:{<operator-expression>}}}
測(cè)試使用5.3的文檔,具體測(cè)試如下:
# 查詢amount鍵值不大于50(即小于等于50)的文檔數(shù)據(jù)
db.inventory.find({amount: {$not: {$gt: 50}}}) # 等同于db.inventory.find({amount:{$lte:50}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
# 查詢條件中的鍵gty,文檔中都不存在無(wú)法匹配表示,所以返回集合所有文檔數(shù)據(jù)。
db.inventory.find({gty: {$not: {$gt: 50}}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795bd")
5.9 "$or" - 選擇出至少滿足數(shù)組中一條表達(dá)式的文檔
執(zhí)行邏輯OR運(yùn)算,指定一個(gè)至少包含兩個(gè)表達(dá)式的數(shù)組,選擇出至少滿足數(shù)組中一條表達(dá)式的文檔。
語(yǔ)法:{$or:[{<expression1>},{<expression2>},...,{<expressionN>}]}
測(cè)試使用5.3的文檔,具體測(cè)試如下:
# 查詢集合中amount的鍵值大于50或者name的鍵值為“t1”的文檔:
db.inventory.find({$or: [{amount: {$gt: 50}}, {name: "t1"}]})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795bd")
5.10 "$exists" - 選擇存在該字段的文檔
如果$exists的值為true,選擇存在該字段的文檔;若值為false則選擇不包含該字段的文檔(我們上面在查詢鍵值為null的文檔時(shí)使用"$exists"判定集合中文檔是否包含該鍵)。
語(yǔ)法:{field:{$exists:<boolean>}}
測(cè)試使用5.3的文檔,并向集合中插入一條amount鍵值為null的文檔
{
"_id" : ObjectId("596c6d761109af02305797a2"),
"name" : "t4",
"amount" : null,
"tags" : ["bag", "school", "book"]
}
具體測(cè)試如下:
# 查詢不存在qty字段的文檔(所有文檔)
db.inventory.find({qty: {$exists: false}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795bd")
"_id" : ObjectId("596c6d761109af02305797a2")
# 查詢amount字段存在,且值不等于16和58的文檔
db.inventory.find({amount: {$exists: true, $nin: [16, 58]}})
如果該字段的值為null,$exists的值為true會(huì)返回該條文檔,false則不返回。
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c6d761109af02305797a2")
# 0條數(shù)據(jù)
db.inventory.find({amount:{$exists:false}})
# 結(jié)果為: Fetched 0 record(s) in 1ms
# 所有的數(shù)據(jù)
db.inventory.find({amount:{$exists:true}})
# 結(jié)果為:
"_id" : ObjectId("596c605b1109af02305795b9")
"_id" : ObjectId("596c605b1109af02305795bb")
"_id" : ObjectId("596c605b1109af02305795bd")
"_id" : ObjectId("596c6d761109af02305797a2")
5.11 "$mod" - 匹配字段值對(duì)取模,值相等的文檔
匹配字段值對(duì)(divisor)取模,值等于(remainder)的文檔。
語(yǔ)法:{field:{$mod:[divisor,remainder]}}
測(cè)試使用5.10更新的文檔,具體測(cè)試如下:
# 查詢集合中amount鍵值為4的0次模數(shù)的所有文檔,例如amount值等于16的文檔
db.inventory.find({amount: {$mod: [4, 0]}})
# 結(jié)果為:
Fetched 0 record(s) in 2ms
# 有些情況下(特殊情況鍵值為null時(shí)),我們可以使用mod操作符替代使用求模表達(dá)式的mod操作符替代使用求模表達(dá)式的where操作符,因?yàn)楹笳叽鷥r(jià)昂貴。
db.inventory.find({$where: "this.amount%4==0"})
# 結(jié)果為:
"_id" : ObjectId("596c6d761109af02305797a2")
注意:返回結(jié)果怎么不一樣。因?yàn)橛幸粭l文檔的amount鍵值為null,javascript中null進(jìn)行數(shù)值轉(zhuǎn)換,會(huì)返回"0"。所以該條文檔匹配where操作符求模式了表達(dá)式。當(dāng)文檔中字段值不存在null,就可以使用where操作符求模式了表達(dá)式。當(dāng)文檔中字段值不存在null,就可以使用mod替代$where的表達(dá)式.
5.12 "$regex" - 對(duì)字符串的執(zhí)行正則匹配
操作符查詢中可以對(duì)字符串的執(zhí)行正則匹配。 MongoDB使用Perl兼容的正則表達(dá)式(PCRE)庫(kù)來(lái)匹配正則表達(dá)式。
語(yǔ)法:# options(使用options(使用regex )
i 如果設(shè)置了這個(gè)修飾符,模式中的字母會(huì)進(jìn)行大小寫(xiě)不敏感匹配。
m 默認(rèn)情況下,PCRE 認(rèn)為目標(biāo)字符串是由單行字符組成的(然而實(shí)際上它可能會(huì)包含多行).如果目標(biāo)字符串 中沒(méi)有 "\n"字符,或者模式中沒(méi)有出現(xiàn)“行首”/“行末”字符,設(shè)置這個(gè)修飾符不產(chǎn)生任何影響。
s 如果設(shè)置了這個(gè)修飾符,模式中的點(diǎn)號(hào)元字符匹配所有字符,包含換行符。如果沒(méi)有這個(gè)修飾符,點(diǎn)號(hào)不匹配換行符。
x 如果設(shè)置了這個(gè)修飾符,模式中的沒(méi)有經(jīng)過(guò)轉(zhuǎn)義的或不在字符類中的空白數(shù)據(jù)字符總會(huì)被忽略,并且位于一個(gè)未轉(zhuǎn)義的字符類外部的#字符和下一個(gè)換行符之間的字符也被忽略。 這個(gè)修飾符使被編譯模式中可以包含注釋。 注意:這僅用于數(shù)據(jù)字符。 空白字符 還是不能在模式的特殊字符序列中出現(xiàn),比如序列 。
注:JavaScript只提供了i和m選項(xiàng),x和s選項(xiàng)必須使用$regex操作符。
測(cè)試使用5.10更新的文檔,具體測(cè)試如下:
# 查詢name鍵值以“4”結(jié)尾的文檔
db.inventory.find({name: /.4/i});
db.inventory.find({name: {$regex: '.4', $options: 'i'}});
# 結(jié)果為:
"_id" : ObjectId("596c6d761109af02305797a2")
5.13 "$where" - 使用任意的JavaScript作為查詢的一部分
操作符功能強(qiáng)大而且靈活,他可以使用任意的JavaScript作為查詢的一部分,包含JavaScript表達(dá)式的字符串或者JavaScript函數(shù)。
新建fruit集合并插入如下文檔:
db.fruit.insert({"apple":1, "banana": 4, "peach" : 4})
db.fruit.insert({"apple":3, "banana": 3, "peach" : 4})
具體測(cè)試如下:
# 比較文檔中的兩個(gè)鍵的值是否相等.例如查找出banana等于peach鍵值的文檔(4種方法):
# JavaScrip字符串形式
db.fruit.find( { $where: "this.banana == this.peach" } )
db.fruit.find( { $where: "obj.banana == obj.peach" } )
# JavaScript函數(shù)形式
db.fruit.find( { $where: function() { return (this.banana == this.peach) } } )
db.fruit.find( { $where: function() { return obj.banana == obj.peach; } } )
# 查出文檔中存在的兩個(gè)鍵的值相同的文檔,JavaScript函數(shù)會(huì)遍歷集合中的文檔:
>db.fruit.find({$where:function () {
for (var current in this) {
for (var other in this) {
if (current != other && this[current] == this[other]) {
return true;
}
}
}
return false;
}});
注意:我們盡量避免使用"Where"査詢,因?yàn)樗鼈冊(cè)谒俣壬弦瘸R?guī)査詢慢很多。每個(gè)文檔都要從BSON轉(zhuǎn)換成JavaScript對(duì)象,然后通過(guò)"Where"査詢,因?yàn)樗鼈冊(cè)谒俣壬弦瘸R?guī)査詢慢很多。每個(gè)文檔都要從BSON轉(zhuǎn)換成JavaScript對(duì)象,然后通過(guò)"where"的表達(dá)式來(lái)運(yùn)行;同樣還不能利用索引。
5.14 "$slice (projection)" - 符控制查詢返回的數(shù)組中元素的個(gè)數(shù)。
語(yǔ)法:db.collection.find( { field: value }, { array: {$slice: count } } );
此操作符根據(jù)參數(shù)"{ field: value }" 指定鍵名和鍵值選擇出文檔集合,并且該文檔集合中指定"array"鍵將返回從指定數(shù)量的元素。如果count的值大于數(shù)組中元素的數(shù)量,該查詢返回?cái)?shù)組中的所有元素的。
- 正數(shù)和負(fù)數(shù)
# 選擇comments的數(shù)組鍵值中前五個(gè)元素。
db.posts.find( {}, { comments: { $slice: 5 } } );
#選擇comments的數(shù)組鍵值中后五個(gè)元素。
db.posts.find( {}, { comments: { $slice: -5 } } );
- 數(shù)組
數(shù)組參數(shù)使用[skip , limit] 格式,其中第一個(gè)值表示在數(shù)組中跳過(guò)的項(xiàng)目數(shù),第二個(gè)值表示返回的項(xiàng)目數(shù)。
# 選擇comments的數(shù)組鍵值中跳過(guò)前20項(xiàng)之后前10項(xiàng)元素
db.posts.find( {}, { comments: { $slice: [ 20, 10 ] } } );
#選擇comments的數(shù)組鍵值中倒數(shù)第20項(xiàng)起前10項(xiàng)元素
db.posts.find( {}, { comments: { $slice: [ -20, 10 ] } } );
5.15 "$elemMatch(projection)"
elemMatch投影操作符將限制查詢返回的數(shù)組字段的內(nèi)容只包含匹配elemMatch投影操作符將限制查詢返回的數(shù)組字段的內(nèi)容只包含匹配elemMatch條件的數(shù)組元素。
注意:
數(shù)組中元素是內(nèi)嵌文檔。
如果多個(gè)元素匹配$elemMatch條件,操作符返回?cái)?shù)組中第一個(gè)匹配條件的元素。
假設(shè)集合school有如下數(shù)據(jù):
{
"_id" : ObjectId("596c711a1109af0230579899"),
"zipcode" : 63109,
"students" : [
{"name" : "john","school" : 102,"age" : 10},
{"name" : "jess","school" : 102,"age" : 11},
{"name" : "jeff","school" : 108,"age" : 15}
]
}
{
"_id" : ObjectId("596c711a1109af023057989b"),
"zipcode" : 63110,
"students" : [
{"name" : "ajax","school" : 100,"age" : 7},
{"name" : "achilles","school" : 100,"age" : 8}
]
}
{
"_id" : ObjectId("596c711a1109af023057989d"),
"zipcode" : 63109,
"students" : [
{"name" : "ajax","school" : 100,"age" : 7},
{"name" : "achilles","school" : 100,"age" : 8}
]
}
{
"_id" : ObjectId("596c711a1109af023057989f"),
"zipcode" : 63109,
"students" : [
{"name" : "barney","school" : 102,"age" : 7}
]
}
具體測(cè)試如下:
#下面的操作將查詢郵政編碼鍵值是63109的所有文檔。
# $elemMatch操作符將返回students數(shù)組中的第一個(gè)匹配條件(內(nèi)嵌文檔的school鍵且值為102)的元素。
db.school.find({zipcode: 63109}, {students: {$elemMatch: {school: 102}}});
# 結(jié)果為:
"_id" : ObjectId("596c711a1109af0230579899")
"_id" : ObjectId("596c711a1109af023057989d")
"_id" : ObjectId("596c711a1109af023057989f")
# 結(jié)果分析:
students數(shù)組包含多個(gè)元素中存在school鍵且值為102的元素,\$elemMatch只返回一個(gè)匹配條件的元素。students數(shù)組包含多個(gè)元素中存在school鍵且值為102的元素,\$elemMatch只返回一個(gè)匹配條件的元素,所以返回"_id":ObjectId("596c711a1109af0230579899")和"_id":ObjectId("596c711a1109af023057989f")
因?yàn)閟tudents數(shù)組中元素?zé)o法匹配\$elemMatch條件,所以查詢結(jié)果不包含"students"字段。因?yàn)閟tudents數(shù)組中元素?zé)o法匹配$elemMatch條件,所以查詢結(jié)果不包含"students"字段,所以返回"_id" : ObjectId("596c711a1109af023057989d")
#$elemMatch可以指定多個(gè)字段的限定條件,下面的操作將查詢郵政編碼鍵值是63109的所有文檔。$elemMatch操作符將返回students數(shù)組中的第一個(gè)匹配條件(內(nèi)嵌文檔的school鍵且值為102且age鍵值大于10)的元素。
db.school.find({zipcode: 63109}, {students: {$elemMatch: {school: 102,age: {$gt: 10}}}});
# 結(jié)果為:
"_id" : ObjectId("596c711a1109af0230579899")
"_id" : ObjectId("596c711a1109af023057989d")
"_id" : ObjectId("596c711a1109af023057989f")
# 結(jié)果分析:
因?yàn)閟tudents數(shù)組中沒(méi)有元素匹配的$elemMatch條件,查詢結(jié)果不包含“students”字段。