MongoDB學(xué)習(xí) (六):查詢(xún)

目錄

查詢(xún)操作

集合查詢(xún)方法 find()

查詢(xún)內(nèi)嵌文檔

查詢(xún)操作符(內(nèi)含 數(shù)組查詢(xún))

"$gt" 、"$gte"、 "$lt"、 "$lte"、"null查詢(xún)"、"$all"、"$size"、"$in"、"$nin"、

"$and"、"$nor"、"$not"、"$or"、"$exists"、"$mod"、"$regex"、"$where"、"$slice"、"$elemMatch"

1.1 集合查詢(xún)方法 find()

db.collection.find()查詢(xún)集合中文檔并返回結(jié)果為游標(biāo)的文檔集合。

語(yǔ)法:db.collection.find(query, projection)

參數(shù)?     類(lèi)型?    描述

query    文檔  可選. 使用查詢(xún)操作符指定查詢(xún)條件

projection?   文檔 ?可選.使用投影操作符指定返回的鍵。查詢(xún)時(shí)返回文檔中所有鍵值, 只需省略該參數(shù)即可(默認(rèn)省略).

返回值: 匹配查詢(xún)條件的文檔集合的游標(biāo). 如果指定投影參數(shù),查詢(xún)出的文檔返回指定的鍵?,"_id"鍵也可以從集合中移除掉。

注意:在mongo shell中我們不需要JavaScript游標(biāo)處理方法就可以直接訪(fǎng)問(wèn)作為查詢(xún)結(jié)果的文檔集合。mongo shell默認(rèn)返回游標(biāo)中的前20條文檔。當(dāng)執(zhí)行查詢(xún)操作時(shí),mongo shell直接自動(dòng)的對(duì)游標(biāo)執(zhí)行迭代操作并顯示前20條文檔。輸入"it"顯示接下來(lái)的20條文檔。

find的第一個(gè)參數(shù)是查詢(xún)條件,其形式也是一個(gè)文檔,決定了要返回哪些文檔,空的査詢(xún)文檔{}會(huì)匹配集合的全部?jī)?nèi)容。要是不指定査詢(xún)文檔,默認(rèn)就是{},如同SQL中"SELECT * FROM TABLENAME"語(yǔ)句。

//將返回集合中所有文檔db.collection.find()//或者db.collection.find({})

第一個(gè)參數(shù)若為鍵/值對(duì)時(shí),查詢(xún)過(guò)程中就意味著執(zhí)行了條件篩選,就如同我們使用Linq查詢(xún)數(shù)據(jù)庫(kù)一樣。下面查詢(xún)操作將返回user集合中age鍵值為16的文檔集合。

//mongo dbdb.user.find({age:16})//Linq to sqldbContext.user.select(p=>p.age==16)

上面的查詢(xún)默認(rèn)執(zhí)行“==”操作(就如同linq中 p.age==16),文檔中若存在相同鍵的值和查詢(xún)文檔中鍵的值相等的話(huà),就會(huì)返回該文檔。

第一個(gè)參數(shù)若包含多個(gè)鍵/值對(duì)(逗號(hào)分隔),則相當(dāng)于查詢(xún)AND組合條件,“條件1 AND條件2 AND…AND 條件N".例如查詢(xún)年齡為28且性別為男性的文檔集合:

//mongo dbdb.user.find({age:28,sex:"male"})//Linq to sqldbContext.user.select(p=>p.age==28&&p.sex=="male")//SQLSELECT * FROM user WHERE age=28AND sex="male"

指定返回的鍵

我們可以通過(guò)find 的第二個(gè)參數(shù)來(lái)指定返回的鍵。

若find不指定第二個(gè)參數(shù),查詢(xún)操作默認(rèn)返回查詢(xún)文檔中所有鍵值。像SQL中我們可以指定查詢(xún)返回字段一樣 ,mongo中也可以指定返回的鍵,這樣我們就可以避免查詢(xún)無(wú)用鍵值查詢(xún)所消耗的資源、會(huì)節(jié)省傳輸?shù)臄?shù)據(jù)量和內(nèi)存消耗。

集合user包含 _id,name,age,sex,email等鍵,如果查詢(xún)結(jié)果想只顯示集合中的"name"和"age"鍵,可以使用如下查詢(xún)返回這些鍵,。

> db.users.find({}, {"name":1,"age":1})

上面查詢(xún)結(jié)果中,"_id"這個(gè)鍵總是被返回,即便是沒(méi)有指定也一樣。但是我們可以顯示的將其從查詢(xún)結(jié)果中移除掉。

> db.users.find({}, {"name":1,"age":1,"_id":0})

在第二個(gè)參數(shù)中,指定鍵名且值為1或者true則是查詢(xún)結(jié)果中顯示的鍵;若值為0或者false,則為不顯示鍵。文檔中的鍵若在參數(shù)中沒(méi)有指定,查詢(xún)結(jié)果中將不會(huì)顯示(_id例外)。這樣我們就可以靈活顯示聲明來(lái)指定返回的鍵。

我們?cè)谑褂肦DMS時(shí),有時(shí)會(huì)對(duì)表中多個(gè)字段之間進(jìn)行比較。如表store中,有銷(xiāo)售數(shù)量soldnum和庫(kù)存數(shù)量stocknum兩個(gè)字段,我們要查詢(xún)表中銷(xiāo)售數(shù)量等于庫(kù)存數(shù)量的記錄時(shí)可以使用下面的sql語(yǔ)句:

SELECT*FROMstoreWHEREsoldnum=stocknum

那么換成mongodb呢,使用find()能實(shí)現(xiàn)類(lèi)似的功能嗎?

> db.store.find ({"soldnum":"stocknum"})//或者> db.store.find ({"stocknum":"soldnum"})

結(jié)果是不行的?。∥覀兛梢允褂?where運(yùn)算符來(lái)進(jìn)行相應(yīng)的操作。

1.2? 查詢(xún)內(nèi)嵌文檔

查詢(xún)文檔有兩種方式,一種是完全匹查詢(xún),另一種是針對(duì)鍵/值對(duì)查詢(xún)。

>db.profile.find()

{"_id" : ObjectId("51d7b0d436332e1a5f7299d6"), "name" : { "first" : Barack", "last" : "Obama" } }

>

內(nèi)嵌文檔的完全匹配查詢(xún)和數(shù)組的完全匹配查詢(xún)一樣,內(nèi)嵌文檔內(nèi)鍵值對(duì)的數(shù)量,順序都必須一致才會(huì)匹配:

> db.profile.find({ name : { first : "Barack", last : "Obama" } });{ "_id" : ObjectId("51d7b0d436332e1a5f7299d6"), "name" : { "first" : Barack", "last" : "Obama" } }

>

//無(wú)任何返回值> db.profile.find({ name : {? last : "Obama" , first : "Barack"} });

>

推薦采用針對(duì)鍵/值對(duì)查詢(xún),通過(guò)點(diǎn)表示法來(lái)精確表示內(nèi)嵌文檔的鍵:

//查詢(xún)結(jié)果一樣db.profile.find({? "name.first" : "Barack" , "name.last" : "Obama"});//或者db.profile.find({? "name.last" : "Obama" , "name.first" : "Barack"} );

運(yùn)行結(jié)果:

査詢(xún)文檔可以包含點(diǎn),來(lái)表達(dá)“深入內(nèi)嵌文檔內(nèi)部”的意思,點(diǎn)表示法也是待插入的文檔不能包含的原因。當(dāng)內(nèi)嵌文檔變得復(fù)雜后,如鍵的值為內(nèi)嵌文檔的數(shù)組,內(nèi)嵌文檔的匹配需要些許技巧,例如使用$elemMatch操作符。

集合blogs有如下文檔:

{"content" : ".....","comment": [

{"author" : "zhangsan","score" : 3,"comment" : "shafa!"},

{"author" : "lisi","score" : 5,"comment" : "lzsb!"}

]

}

我們想查詢(xún)?cè)u(píng)論中用戶(hù)“zhangsan”是否有評(píng)分超過(guò)4分的評(píng)論內(nèi)容,但我們利用“點(diǎn)表示法”直接寫(xiě)是有問(wèn)題的,這條查詢(xún)條件和數(shù)組中不同的文檔進(jìn)行了匹配!

> db.blogs.find({"comment.author":"zhangsan", "comment.score":{"$gte":4}});

上面的結(jié)果不是我們期望的,下面使用“$elemMatch”操作符即可將一組條件限定到數(shù)組中單條文檔的匹配上:

> db.blogs.find({"comment":{"$elemMatch":{"author":"zhangsan","score":{"$gt":4}}}});> db.blogs.find({"comment":{"$elemMatch":{"author":"zhangsan","score":{"$gt":2}}}});

1.3 查詢(xún)操作符

下面我們將配合查詢(xún)操作符來(lái)執(zhí)行復(fù)雜的查詢(xún)操作,比如元素查詢(xún)、 邏輯查詢(xún) 、比較查詢(xún)操作。

我們使用下面的比較操作符"$gt" 、"$gte"、 "$lt"、 "$lte"(分別對(duì)應(yīng)">"、 ">=" 、"<" 、"<="),組合起來(lái)進(jìn)行范圍的查找。例如查詢(xún)年齡為16-18歲(包含16但不含18)的用戶(hù):

>db.user.find( { age: { $gte:16,$lt:18} }

我們可以使用"$ne"來(lái)進(jìn)行"不相等"操作。例如查詢(xún)年齡不為18歲的用戶(hù):

>db.user.find( { age: {$ne:18} }

精確匹配日期要精確到毫秒,然而我們通常只是想得到關(guān)于一天、一周或者是一個(gè)月的數(shù)據(jù),我們可以使用"gt"、"gt"、"lt"進(jìn)行范圍査詢(xún)。例如,要査找在1990年1月1日出生的用戶(hù):

>? ? start =newDate("1990/01/01")>? ? db.users.find({"birthday": {"$lt": start}})

鍵值為null查詢(xún)操作

如何檢索出sex鍵值為null的文檔,我們使用"in"、"in"、"where"操作符,"$in"判斷鍵值是否為null,"$exists"判定集合中文檔是否包含該鍵。

//集合中有一條sex鍵值為null的文檔{"name":"xiaoming","age":20,"sex":"male"}

{"name":"xiaohong","age":22,"sex":"female"}

{"name":"lilei","age":24,"sex":null}//返回文檔中存在sex鍵,且值為null的文檔db.users.find({sex:{$in:[null],$exists:true}})//返回文檔中存在birthday鍵,且值為null的文檔//文檔沒(méi)有birthday鍵,所以結(jié)果為空db.users.find({birthday:{$in:[null],$exists:true}})

運(yùn)行截圖:

我們也可以運(yùn)行如下語(yǔ)句:

> db.users.find({sex:null})

查詢(xún)結(jié)果跟語(yǔ)句"db.users.find({sex:{in:[null],in:[null],exists:true }})"一樣

但是當(dāng)為我們運(yùn)行下面語(yǔ)句時(shí),發(fā)現(xiàn)查詢(xún)結(jié)果跟語(yǔ)句"db.users.find({birthday:{in:[null],in:[null],exists:true }})"不一樣!

> db.users.find({birthday:null})

查詢(xún)返回了所有的文檔!

因?yàn)閚ull不僅僅匹配自身,而且匹配鍵“不存在的”文檔,集合眾文檔都不存在"birthday"鍵,都匹配查詢(xún)條件,所以上面的語(yǔ)句會(huì)返回所有的文檔!

我們最好使用db.users.find({sex:{in:[null],in:[null],exists:true }})這種格式。

下面先向集合inventory插入3條數(shù)據(jù)(下面的演示基于此數(shù)據(jù)),文檔內(nèi)容如下:

{"name":"t1","amount":16,"tags":[ "school", "book", "bag", "headphone", "appliances" ]}

{"name":"t2","amount":50,"tags":[ "appliances", "school", "book" ]}

{"name":"t3","amount":58,"tags":[ "bag", "school", "book" ]}

"$all"

匹配那些指定鍵的鍵值中包含數(shù)組,而且該數(shù)組包含條件指定數(shù)組的所有元素的文檔,數(shù)組中元素順序不影響查詢(xún)結(jié)果。

語(yǔ)法: { field: { $all: [ , ... ] }

查詢(xún)出在集合inventory中?tags鍵值包含數(shù)組,且該數(shù)組中包含appliances、school、book元素的所有文檔:

db.inventory.find( { tags: { $all: [ "appliances", "school", "book" ] } } )

該查詢(xún)將匹配tags鍵值包含如下任意數(shù)組的所有文檔:

[ "school", "book", "bag", "headphone", "appliances"]

["appliances", "school", "book" ]

查詢(xún)結(jié)果:

文檔中鍵值類(lèi)型不是數(shù)組,也可以使用$all操作符進(jìn)行查詢(xún)操作,如下例所示"$all"對(duì)應(yīng)的數(shù)組只有一個(gè)值,那么和直接匹配這個(gè)值效果是一樣的。

//查詢(xún)結(jié)果是相同的,匹配amount鍵值等于50的文檔db.inventory.find( { amount: {$all:[50]}} )

db.inventory.find( { amount:50}} )

要是想查詢(xún)數(shù)組指定位置的元素,則需使用key.index語(yǔ)法指定下標(biāo),例如下面查詢(xún)出tags鍵值數(shù)組中第2個(gè)元素為"school"的文檔:

> db.inventory.find({"tags.1":"school"})

數(shù)組下標(biāo)都是從0開(kāi)始的,所以查詢(xún)結(jié)果返回?cái)?shù)組中第2個(gè)元素為"school"的文檔:

"$size"

用其查詢(xún)指定長(zhǎng)度的數(shù)組。

語(yǔ)法:{field: {$size: value} }

查詢(xún)集合中tags鍵值包含有3個(gè)元素的數(shù)組的所有文檔:

> db.inventory.find({tags:{$size:3}})

文檔"{"name":"t1","amount":16,"tags":[ "school", "book", "bag", "headphone", "appliances" ]}",tags鍵值數(shù)組包含四個(gè)元素,所以不匹配查詢(xún)條件。查詢(xún)結(jié)果:

size必須制定一個(gè)定值,不能接受一個(gè)范圍值,不能與其他查詢(xún)子句組合(比如"size必須制定一個(gè)定值,不能接受一個(gè)范圍值,不能與其他查詢(xún)子句組合(比如"gt")。但有時(shí)查詢(xún)需求就是需要一個(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)范圍查詢(xún)db.collection.find({count : {$gt:2}})

"$in"

匹配鍵值等于指定數(shù)組中任意值的文檔。類(lèi)似sql中in.

語(yǔ)法: { field: { $in: [, , ... ] } }

"$nin"

匹配鍵不存在或者鍵值不等于指定數(shù)組的任意值的文檔。類(lèi)似sql中not in(SQL中字段不存在使用會(huì)有語(yǔ)法錯(cuò)誤).

語(yǔ)法: { field: { $nin: [ , ... ]} }

查詢(xún)出amount鍵值為16或者50的文檔:

db.inventory.find( { amount: { $in: [ 16, 50 ] } } )

//查詢(xún)出amount鍵值不為16或者50的文檔db.inventory.find( { amount: { $nin: [ 16, 50] } } )//查詢(xún)出qty鍵值不為16或50的文檔,由于文檔中都不存在鍵qty,所以返回所有文檔db.inventory.find( { qty: { $nin: [ 16, 50 ] } } )

文檔中鍵值類(lèi)型不是數(shù)組,也可以使用$all操作符進(jìn)行查詢(xún)操作,如下例所示"$in"對(duì)應(yīng)的數(shù)組只有一個(gè)值,那么和直接匹配這個(gè)值效果是一樣的。

//查詢(xún)結(jié)果是相同的,匹配amount鍵值等于50的文檔db.inventory.find( { amount: {$in:[50]}} )

db.inventory.find( { amount:50}} )

"$and"

指定一個(gè)至少包含兩個(gè)表達(dá)式的數(shù)組,選擇出滿(mǎn)足該數(shù)組中所有表達(dá)式的文檔。$and操作符使用短路操作,若第一個(gè)表達(dá)式的值為“false”,余下的表達(dá)式將不會(huì)執(zhí)行。

語(yǔ)法: { $and: [ { }, { } , ... , { } ] }

查詢(xún)name鍵值為“t1”,amount鍵值小于50的文檔:

db.inventory.find({ $and: [ { name: "t1" }, { amount: { $lt:50 } } ] } )

對(duì)于下面使用逗號(hào)分隔符的表達(dá)式列表,MongoDB會(huì)提供一個(gè)隱式的$and操作:

//等同于{ $and: [ { name: "t1" }, { amount: { $lt:50 } } ] }db.inventory.find({ name: "t1" , amount: { $lt:50 }} )

"$nor"

執(zhí)行邏輯NOR運(yùn)算,指定一個(gè)至少包含兩個(gè)表達(dá)式的數(shù)組,選擇出都不滿(mǎn)足該數(shù)組中所有表達(dá)式的文檔。

語(yǔ)法: { $nor: [ { }, { }, ... { } ] }

查詢(xún)name鍵值不為“t1”,amount鍵值不小于50的文檔:

db.inventory.find( { $nor: [ { name: "t1" }, { qty: { $lt: 50 } } ] } )

若是文檔中不存在表達(dá)式中指定的鍵,表達(dá)式值為false; false nor false 等于 true,所以查詢(xún)結(jié)果返回集合中所有文檔:

db.inventory.find( { $nor: [ { sale:true}, { qty: { $lt: 50 } } ] } )

"$not"

執(zhí)行邏輯NOT運(yùn)算,選擇出不能匹配表達(dá)式的文檔 ,包括沒(méi)有指定鍵的文檔。$not操作符不能獨(dú)立使用,必須跟其他操作一起使用(除$regex)。

語(yǔ)法: { field: { $not: { } } }

查詢(xún)amount鍵值不大于50(即小于等于50)的文檔數(shù)據(jù)

db.inventory.find( { amount: { $not: { $gt:50} } } )//等同于db.inventory.find( { amount:? { $lte: 50 } } )

查詢(xún)條件中的鍵gty,文檔中都不存在無(wú)法匹配表示,所以返回集合所有文檔數(shù)據(jù)。

db.inventory.find( { gty: { $not: { $gt: 50 } } } )

"$or"

執(zhí)行邏輯OR運(yùn)算,指定一個(gè)至少包含兩個(gè)表達(dá)式的數(shù)組,選擇出至少滿(mǎn)足數(shù)組中一條表達(dá)式的文檔。

語(yǔ)法: { $or: [ { }, { }, ... , { } ] }

查詢(xún)集合中amount的鍵值大于50或者name的鍵值為“t1”的文檔:

db.inventory.find( { $or: [ { amount: { $gt: 50 } }, { name: "t1" } ] } )

"$exists"

如果$exists的值為true,選擇存在該字段的文檔;若值為false則選擇不包含該字段的文檔(我們上面在查詢(xún)鍵值為null的文檔時(shí)使用"$exists"判定集合中文檔是否包含該鍵)。

語(yǔ)法: { field: { $exists: } }

//查詢(xún)不存在qty字段的文檔(所有文檔)db.inventory.find( { qty: { $exists:false} })//查詢(xún)amount字段存在,且值不等于16和58的文檔db.inventory.find( { amount: { $exists:true, $nin: [ 16, 58 ] } } )

如果該字段的值為null,$exists的值為true會(huì)返回該條文檔,false則不返回。

//向集合中插入一條amount鍵值為null的文檔{"name":"t4","amount":null,"tags":[ "bag", "school", "book"]}//0條數(shù)據(jù)db.inventory.find( { amount: { $exists:false} } )//所有的數(shù)據(jù)db.inventory.find( { amount: { $exists:true} } )

"$mod"

匹配字段值對(duì)(divisor)取模,值等于(remainder)的文檔。

語(yǔ)法: { field: { $mod: [ divisor, remainder ]} }

查詢(xún)集合中 amount 鍵值為 4 的 0 次模數(shù)的所有文檔,例如 amount 值等于 16 的文檔

db.inventory.find( { amount: { $mod: [ 4, 0 ] } } )

有些情況下(特殊情況鍵值為null時(shí)),我們可以使用mod操作符替代使用求模表達(dá)式的mod操作符替代使用求模表達(dá)式的where操作符,因?yàn)楹笳叽鷥r(jià)昂貴。

db.inventory.find( { $where: "this.amount % 4 == 0" } )

注意:返回結(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á)式.

"$regex"

操作符查詢(xún)中可以對(duì)字符串的執(zhí)行正則匹配。 MongoDB使用Perl兼容的正則表達(dá)式(PCRE)庫(kù)來(lái)匹配正則表達(dá)式.

我們可以使用正則表達(dá)式對(duì)象或者$regex操作符來(lái)執(zhí)行正則匹配:

//查詢(xún)name鍵值以“4”結(jié)尾的文檔db.inventory.find( { name: /.4/i } );

db.inventory.find( { name: { $regex:'.4', $options: 'i' } } );

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)義的或不在字符類(lèi)中的空白數(shù)據(jù)字符總會(huì)被忽略,并且位于一個(gè)未轉(zhuǎn)義的字符類(lèi)外部的#字符和下一個(gè)換行符之間的字符也被忽略。 這個(gè)修飾符使被編譯模式中可以包含注釋。 注意:這僅用于數(shù)據(jù)字符。 空白字符 還是不能在模式的特殊字符序列中出現(xiàn),比如序列 。

注:JavaScript只提供了i和m選項(xiàng),x和s選項(xiàng)必須使用$regex操作符。

"$where"

操作符功能強(qiáng)大而且靈活,他可以使用任意的JavaScript作為查詢(xún)的一部分,包含JavaScript表達(dá)式的字符串或者JavaScript函數(shù)。

新建fruit集合并插入如下文檔:

//插入兩條數(shù)據(jù)db.fruit.insert({"apple":1, "banana": 4, "peach" : 4})

db.fruit.insert({"apple":3, "banana": 3, "peach" : 4})

比較文檔中的兩個(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() {returnobj.banana == obj.peach; } } )

查出文檔中存在的兩個(gè)鍵的值相同的文檔,JavaScript函數(shù)會(huì)遍歷集合中的文檔:

>db.fruit.find({$where:function() {for(varcurrentinthis) {for(varotherinthis) {if(current != other &&this[current] ==this[other]) {returntrue;

}

}

}returnfalse;

}});

注意:我們盡量避免使用"Where"査詢(xún),因?yàn)樗鼈冊(cè)谒俣壬弦瘸R?guī)査詢(xún)慢很多。每個(gè)文檔都要從BSON轉(zhuǎn)換成JavaScript對(duì)象,然后通過(guò)"Where"査詢(xún),因?yàn)樗鼈冊(cè)谒俣壬弦瘸R?guī)査詢(xún)慢很多。每個(gè)文檔都要從BSON轉(zhuǎn)換成JavaScript對(duì)象,然后通過(guò)"where"的表達(dá)式來(lái)運(yùn)行;同樣還不能利用索引。

"$slice (projection)"

$slice操作符控制查詢(xún)返回的數(shù)組中元素的個(gè)數(shù)。

語(yǔ)法:db.collection.find( { field: value }, { array: {$slice: count } } );

此操作符根據(jù)參數(shù)"{ field: value }" 指定鍵名和鍵值選擇出文檔集合,并且該文檔集合中指定"array"鍵將返回從指定數(shù)量的元素。如果count的值大于數(shù)組中元素的數(shù)量,該查詢(xún)返回?cái)?shù)組中的所有元素的。

$slice接受多種格式的參數(shù) 包含負(fù)數(shù)和數(shù)組:

//選擇comments的數(shù)組鍵值中前五個(gè)元素。db.posts.find( {}, { comments: { $slice: 5} } );//選擇comments的數(shù)組鍵值中后五個(gè)元素。db.posts.find( {}, { comments: { $slice: -5 } } );

下面介紹指定一個(gè)數(shù)組作為參數(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 ] } } );

"$elemMatch(projection)"

elemMatch投影操作符將限制查詢(xún)返回的數(shù)組字段的內(nèi)容只包含匹配elemMatch投影操作符將限制查詢(xún)返回的數(shù)組字段的內(nèi)容只包含匹配elemMatch條件的數(shù)組元素。

注意:

數(shù)組中元素是內(nèi)嵌文檔。

如果多個(gè)元素匹配$elemMatch條件,操作符返回?cái)?shù)組中第一個(gè)匹配條件的元素。

假設(shè)集合school有如下數(shù)據(jù):

{

_id:1,

zipcode:63109,

students: [

{ name:"john", school: 102, age: 10},

{ name:"jess", school: 102, age: 11},

{ name:"jeff", school: 108, age: 15}

]

}

{

_id:2,

zipcode:63110,

students: [

{ name:"ajax", school: 100, age: 7},

{ name:"achilles", school: 100, age: 8},

]

}

{

_id:3,

zipcode:63109,

students: [

{ name:"ajax", school: 100, age: 7},

{ name:"achilles", school: 100, age: 8},

]

}

{

_id:4,

zipcode:63109,

students: [

{ name:"barney", school: 102, age: 7},

]

}

下面的操作將查詢(xún)郵政編碼鍵值是63109的所有文檔。$elemMatch操作符將返回students數(shù)組中的第一個(gè)匹配條件(內(nèi)嵌文檔的school鍵且值為102)的元素。

db.school.find( { zipcode: 63109 },{ students: { $elemMatch: { school: 102 } } } );

查詢(xún)結(jié)果:

_id為1的文檔,students數(shù)組包含多個(gè)元素中存在school鍵且值為102的元素,$elemMatch只返回一個(gè)匹配條件的元素。

_id為3中的文檔,因?yàn)閟tudents數(shù)組中元素?zé)o法匹配$elemMatch條件,所以查詢(xún)結(jié)果不包含"students"字段。

$elemMatch可以指定多個(gè)字段的限定條件,下面的操作將查詢(xún)郵政編碼鍵值是63109的所有文檔。$elemMatch操作符將返回?students數(shù)組中的第一個(gè)匹配條件(內(nèi)嵌文檔的school鍵且值為102且age鍵值大于10)的元素。

db.school.find( { zipcode: 63109 },{ students: { $elemMatch: { school: 102, age: { $gt: 10} } } } );

_id等于3 和4的文檔,因?yàn)閟tudents數(shù)組中沒(méi)有元素匹配的$elemMatch條件,查詢(xún)結(jié)果不包含“?students”字段。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容