MongoDB查询内嵌文档
转载请出自出处:http://eksliang.iteye.com/blog/2177301
一、概述
有两种方法可以查询内嵌文档:查询整个文档;针对键值对进行查询。这两种方式是不同的,下面我通过例子进行分别说明。
二、查询整个文档
例如:有如下文档
db.emp.insert({ "id":"A001", "name":{ "first":"Carey", "last":"Ickes" }, "age":25 })
参考实例:查询name等于"Carey Ickes"的人可以这样查询
db.emp.find({"name":{"first":"Carey","last":"Ickes"}})这种查询会去精确匹配整个内嵌文档,如果Carey决定添加一个中间名的键,那么这个查询就用不了,因为查询条件不在与整个内嵌文档相匹配。而且这种查询还与顺序有关,如果查询条件换成{"last":"Ickes","first":"Carey"},也会什么也匹配不到。
三、键值对查询
我们一般在查询时,不会去匹配整个内嵌文档,通常只针对内嵌文档的特定键值去查询。怎么做?
答:查询文档时,可以使用"."来表示进入内嵌文档。
参考实例:
> db.emp.find({"name.last":"Ickes","name.first":"Carey"})现在,如Ickes增加了更多的键,这个查询依然会匹配他的姓跟名
四、数组里面包含内嵌文档的查询
这种查询相对来说比较复杂一点,所以内嵌文档的匹配也需要有些技巧。例如下面的博客文档中有一个commens:键用来保存别人的评论信息。
db.blog.insert({ "_id":"B001", "title":"MongoDB查询", "comments":[ {"name":"ickes","score":3,"comment":"nice"}, {"name":"xl","score":4,"comment":"nice"}, {"name":"eksliang","score":5,"comment":"nice"}, {"name":"ickes","score":6,"comment":"nice"} ] })现在要查询由ickes评论的且5分以上文章
- 不能使用db.blog.find({"comments":{"name":"ickes","score":{"$gt":5}})去查,因为内嵌文档的匹配是精确匹配,必须要匹配完整的文档,而这个查询不会匹配comment键
- 不能使用db.blog.find({"comments":{"name":"ickes","score":{"$gt":5},"comment":"nice"}})去查,还是那句话,文档的匹配时精确匹配,这里使用了$gt作为范围,所以也查不到
- 不能使用db.blog.find({"comments.name":"ickes","comments.score":{"$gt":5}})去查,前面讲查询条件的时候说过,查询条件里面的键值对会解释为AND,但是对于数组的内嵌文档他会解释为OR的关系,也就是说上面实际是这样的comments.name:ickes或者comments.score":{"$gt":5},这明显不行吗!(注意如果内嵌文档不在数组中,还是AND,所以我才把这个拿出来单独讨论)
那对于数组里面的内嵌文档到底怎么办?应该这么办,如下所示
这里需要使用"$elemMatch"操作符,仅当这种时候才使用这个操作符
参考实例:
db.blog.find({"comments":{ "$elemMatch":{"name":"ickes","score":{"$gt":5}} }})
五、返回与查询条件相匹配的任意一个数组元素
我们可以使用"$slice"操作符进行数组元素返回限制,但是当数组里面保存的是文档的时候,我就想返回与我查询条件相匹配的那个元素,其他的不要,怎么做?有技巧的哦!
文档结构如下:
db.blog.insert({ "_id":"B001", "title":"MongoDB查询", "comments":[ {"name":"ickes","score":3,"comment":"nice"}, {"name":"xl","score":4,"comment":"nice"}, {"name":"eksliang","score":5,"comment":"nice"}, {"name":"ickes","score":6,"comment":"nice"} ] })
参考实例:
db.blog.find({"comments":{ "$elemMatch":{"name":"ickes","score":{"$gt":5}}}}, {"comments.$":1}--第二个参数是限制返回数据的,别看错了,这是第二个参数 )
返回结果如下:仅返回与当前查询条件相匹配的那个内嵌文档。
{ "_id" : "B001", "comments" : [ { "name" : "ickes", "score" : 6, "comment" : "nice" } ] }
如果当前查询有多个内嵌文档匹配,只会返回第一个。