2012-01-17 129 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”})