2011-02-11 93 views
19

我在下面有一個查詢。我想得到4到6之間的項目,所以只有a:1應該匹配,因爲它的值爲b。

> db.test.find({ b : { $gt : 4 }, b: {$lt : 6}}); 
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 3, 4, 5 ] } 
{ "_id" : ObjectId("4d54d0074364000000004332"), "a" : 2, "b" : [ 2, 4, 6, 8 ] } 
> 

有人可以告訴爲什麼a:2匹配這個查詢嗎?我真的不明白爲什麼它會被退回。

我也試了一下在本教程規定,但ID似乎沒有工作:

> db.test.find({ b : { $gt : 4, $lt : 6}}); 
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 3, 4, 5 ] } 
{ "_id" : ObjectId("4d54d0074364000000004332"), "a" : 2, "b" : [ 2, 4, 6, 8 ] } 
> 

而這一次,以避免有關GT任何混淆/ GTE

> db.test.find({b: {$gt: 4.5, $lt: 5.5}}); 
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 3, 4, 5 ] } 
{ "_id" : ObjectId("4d54d0074364000000004332"), "a" : 2, "b" : [ 2, 4, 6, 8 ] } 
> 

只有一個:1應該返回。

至於建議,我給了$ elemMatch一個嘗試,但它似乎沒有工作,要麼(的ObjectID是不同的,因爲我是在不同的機器上)被送回

> db.test.find(); 
{ "_id" : ObjectId("4d5a24a5e82e00000000433f"), "a" : 1, "b" : [ 2, 3, 4, 5 ] } 
{ "_id" : ObjectId("4d5a24bbe82e000000004340"), "a" : 2, "b" : [ 2, 4, 6, 8 ] } 
> db.test.find({b: {$elemMatch: {$gt : 4, $lt: 6 }}}); 
> 

沒有文檔。

+0

其實,這兩份文件應返回,這個問題的意思是「給我其中'B'具有的值是4和6之間的所有文件」,這是滿意由兩個文件。你能否更詳細地解釋它想要查詢的內容?爲什麼要找到第一個文件,而不是第二個? – Theo

+0

正如你上面所說的,我想要所有ab在4和6之間的文檔。只有a:1滿足這個(不是兩個),因爲a:2不包含4和6之間的任何值(使用gt和lt排除4和6他們自己在哪裏,包括它們在內)。我嘗試了一個不同的查詢(請參閱編輯的問題),它更清晰,但仍然無法正常工作... – paullb

+1

我明白你的意思了,我把它當作一個範圍來考慮(範圍通常包括第一個元素) ,但當然不是,這是嚴格的小於和大於。我已經刪除了我的回答,因爲現在很清楚它是錯誤的。 – Theo

回答

51

這是一個非常令人困惑的話題。我在10gen工作,我不得不花一段時間來圍繞它;

讓我們來看看查詢引擎如何處理這個查詢。

這裏再次查詢:

> db.test.find({ b : { $gt : 4, $lt : 6}}); 

當它到達這似乎是不應該匹配記錄...

{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 4, 6, 8 ] } 

比賽是不反對的每個元素進行數組,而是作爲一個整體對陣。

比較是分三步進行:

步驟1:查找其中b具有一個值的所有文檔大於4

B:[2,4,6,8]匹配,因爲6 & 8是大於4

步驟2:查找其中b具有值小於6

b中的所有文件:[2,4,6,8]匹配ES因爲2 & 4是小於6

步驟3:查找,在這兩個步驟1 & 2.

匹配該組文檔與B中的文件:[2,4,6,8]匹配兩個步驟1 & 2,因此它作爲匹配返回。請注意,此步驟中的結果也會被重複刪除,因此同一個文檔將不會被返回兩次。

如果您希望將查詢應用於數組的各個元素而不是整個數組,則可以使用$ elemMatch運算符。例如

> db.temp.find({b: {$elemMatch: {$gt: 4, $lt: 5}}}) 
> db.temp.find({b: {$elemMatch: {$gte: 4, $lt: 5}}}) 
    { "_id" : ObjectId("4d558b6f4f0b1e2141b66660"), "b" : [ 2, 3, 4, 5, 6 ] } 
+0

謝謝Jared,爲我們打好了答案。然而,嘗試它後,它似乎並不奏效。 (我試過了「db.test.find({b:{$ elemMatch:{$ gt:4,$ lt:6}}});」就像你描述的那樣。在這個? – paullb

+0

奇怪。它適用於我。 > db.array2.save({b:[2,3,4,5]}) > db.array2.save({b:[2,4, 6,8]}) > db.array2.find({b:{$ elemMatch:{$ gt:4,$ lt:6}}}){「_id」:ObjectId(「4d5a9268ec5855af36625ed6」),「b 「:[2,3,4,5]} > 你使用的是什麼版本的MongoDB?$ elemMatch增加了1.3.1,所以如果你仍然使用1.2,它將不起作用。 – jared

+0

沒有在這裏工作只是複製並粘貼你的查詢(插入然後查詢),我有1.6.5,看起來可能是一個bug:http://jira.mongodb.org/browse/SERVER-1264 – paullb

-9

因爲您沒有檢查文檔。

http://www.mongodb.org/display/DOCS/Advanced+Queries

並檢查頁上的 「範圍」。

也不是你的查詢語法正確的(比較反對的例子)

也沒有你的「爲什麼:2」的問題的一部分,任何意義,因爲「A」在您的查詢是不參與。如果您想搜索:1,則必須將其包含在查詢中。

請記住,除非您使用$或操作符,否則所有查詢子句都默認爲AND。

+0

此外:如果您對字段子集感興趣:http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields –

+0

感謝您指出該頁面上的範圍示例。我曾看過這個頁面,但錯過了範圍部分。語法顯然是正確的,因爲查詢執行,但我沒有利用範圍因素。 「爲什麼a:2」確實很有意義,因爲它唯一標識每一行,因此不需要參與查詢。我還應該指出,如果子句被解釋爲AND,那麼我的查詢仍然應該正確地取範圍。 所以謝謝你的鏈接,但不要感謝一般的粗魯。 – paullb

+0

一般粗魯嗎?請看看教程。 –

0
.find({$and:[ {b:{$gt:4}}, {b:{$lt:6}} ]}) 
+3

否。接受的答案中顯示的語法是正確的,並且已經是「和」操作。這是一個簡潔的例子,也是可讀語法的一個壞例子。 –

4

$ GT

Syntax: {field: {$gt: value} } 

例如:

db.inventory.find({ qty: { $gt: 20 } }) 

$ LT

Syntax: {field: {$lt: value} } 

例如:

db.inventory.find({ qty: { $lt: 20 } }) 

EG2:

db.inventory.find({ qty : { $gt : 20, $lt : 60}});