2012-01-17 126 views
1

文檔結構的例子是:MongoDB的嵌套數組搜索

{ 
    "dob": "12-13-2001", 
    "name": "Kam", 

    "visits": { 
    "0": { 
     "service_date": "12-5-2011", 
     "payment": "40", 
     "chk_number": "1234455", 
    }, 
    "1": { 
     "service_date": "12-15-2011", 
     "payment": "45", 
     "chk_number": "3461234", 
    }, 
    "2": { 
     "service_date": "12-25-2011", 
     "payment": "25", 
     "chk_number": "9821234", 
    } 
    } 
} 


{ 
    "dob": "10-01-1998", 
    "name": "Sam", 

    "visits": { 
    "0": { 
     "service_date": "12-5-2011", 
     "payment": "30", 
     "chk_number": "86786464", 
    }, 
    "1": { 
     "service_date": "12-15-2011", 
     "payment": "35", 
     "chk_number": "45643461234", 
    }, 
    "2": { 
     "service_date": "12-25-2011", 
     "payment": "20", 
     "chk_number": "4569821234", 
    } 
    } 
} 

在PHP我想列出所有這些「訪問」的信息(和相應的「名稱」)爲其付款小於「30」。

我想打印只有「付款」<「30」而不是其他人的訪問。這樣的查詢是否可能,或者我必須先使用搜索來獲取整個文檔,然後使用PHP來選擇此類訪問?

回答

18

在示例文檔中,「支付」值是作爲字符串給出的, $ lt命令。對於這個迴應,我已經將它們轉換爲整數。

對於MongoDB,通配符查詢是不可能的,所以對於給定的文檔結構,必須知道子文檔的關鍵字(0,1,2等)。例如,下面的查詢將工作:

> db.test.find({"visits.2.payment":{$lt:35}}) 

然而,

> db.test.find({"visits.payment":{$lt:35}}) 

不會在這種情況下工作,

> db.test.find({"visits.*.payment":{$lt:35}}) 

也不會返回任何結果。

爲了能夠查詢嵌入的「訪問」的文件,你必須改變你的文件結構,使「訪問」到一個數組或嵌入文檔,像這樣:

> db.test2.find().pretty() 
{ 
    "_id" : ObjectId("4f16199d3563af4cb141c547"), 
    "dob" : "10-01-1998", 
    "name" : "Sam", 
    "visits" : [ 
     { 
      "service_date" : "12-5-2011", 
      "payment" : 30, 
      "chk_number" : "86786464" 
     }, 
     { 
      "service_date" : "12-15-2011", 
      "payment" : 35, 
      "chk_number" : "45643461234" 
     }, 
     { 
      "service_date" : "12-25-2011", 
      "payment" : 20, 
      "chk_number" : "4569821234" 
     } 
    ] 
} 

現在,您可查詢所有的嵌入文檔的「訪問」:

> db.test2.find({"visits.payment":{$lt:35}}) 

欲瞭解更多信息,請參見上點標記蒙戈文檔:

http://www.mongodb.org/display/DOCS/Dot+Notation+%28Reaching+into+Objects%29

現在回到問題的第二部分:不可能僅返回嵌入式文檔的條件子集。

對於任一種文檔格式,都不可能返回僅包含與查詢匹配的子文檔的文檔。如果其中一個子文檔與查詢匹配,那麼整個文檔與查詢匹配,並且將被返回。

按照蒙戈文件「檢索字段的子集」

http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields

我們可以返回嵌入文檔的部分,像這樣:

> db.test2.find({"visits.payment":{$lt:35}},{"visits.service_date":1}).pretty() 
{ 
    "_id" : ObjectId("4f16199d3563af4cb141c547"), 
    "visits" : [ 
     { 
      "service_date" : "12-5-2011" 
     }, 
     { 
      "service_date" : "12-15-2011" 
     }, 
     { 
      "service_date" : "12-25-2011" 
     } 
    ] 
} 

但我們不能有一些有條件的檢索子文件。我們可以得到最接近的是$分割運算,但這不是有條件的,你必須先了解每個子文檔的數組中的位置:

http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements

爲了使應用程序要僅顯示與查詢匹配的嵌入式文檔,它必須以編程方式完成。

+0

Thankyou馬克的解釋..我想我將不得不使用PHP從完整的文件檢索信息。 – pun

1

你可以試試:

$results = $mongodb->find(array("visits.payment" => array('$lt' => 30))); 

但我不知道這是否會工作,因爲visits是一個對象。順便說一句,從你發佈的內容來看,它可以被轉移到數組(或者應該,因爲數字屬性名稱會導致混淆)

+0

但是,這將返回一個包含 「付款」< 「30」 的整個文檔,包括訪問對於其中「付款「> 30.感謝您的幫助 – pun

+0

是的,但不包括只有付款> 30的文件,這是您可以做的最好的。 –

0

嘗試 - db.test2.find({ 「visits.payment」: 「35」})