MongoDB查询内嵌文档

一、概述

   有两种方法可以查询内嵌文档:查询整个文档;针对键值对进行查询。这两种方式是不同的,下面我通过例子进行分别说明。

二、查询整个文档

例如:有如下文档

class GoalReportMongoModel(Document):

    id = StringField(primary_key=True)
    user_id = StringField()
    date = StringField()
    update_time = LongField()
    goals = ListField()
    leader_id = StringField()
    comment = StringField()
    checked = BooleanField()
    check_time = LongField()

参考示例:查询date 为2016-08-05 user_id 为U06UGFL12
可以这样查询

db.getCollection("goal_report").find({date:'2016-08-05',user_id:'U06UGFL12'})

这种查询会去精确匹配整个内嵌文档

三、键值对查询

我们一般在查询时,不会去匹配整个内嵌文档,通常只针对内嵌文档的特定键值去查询。怎么做?

答:查询文档时,可以使用"."来表示进入内嵌文档。

参考实例:

 db.getCollection("goal_report").find({"goals.goal":'价值目标COO-1',"goals.assigner":'san.zhang'})

查询结果

{ 
    "_id" : "U06UGFL12_2016-08-05", 
    "user_id" : "U06UGFL12", 
    "date" : "2016-08-05", 
    "update_time" : NumberLong(1470397732), 
    "goals" : [
        {
            "status" : "ensure", 
            "criterion_ok" : true, 
            "user_id" : "U06UGFL12", 
            "goal" : "价值目标COO-1", 
            "assigner" : "san.zhang", 
            "tool" : "", 
            "method_ok" : true, 
            "done_time" : NumberInt(0), 
            "method" : "", 
            "reason" : "本周",
            "criterion" : "", 
            "goal_type" : "valuable", 
            "expire_time" : NumberInt(0), 
            "execution" : NumberInt(2), 
            "id" : NumberInt(1135241564), 
            "planh" : ""
        }, 
       {
            "status" : "ensure", 
            "criterion_ok" : true, 
            "user_id" : "U06UGF232", 
            "goal" : "价值目标COO-2", 
            "assigner" : "san.zhang", 
            "tool" : "", 
            "method_ok" : true, 
            "done_time" : NumberInt(0), 
            "method" : "", 
            "reason" : "本周",
            "criterion" : "", 
            "goal_type" : "valuable", 
            "expire_time" : NumberInt(0), 
            "execution" : NumberInt(2), 
            "id" : NumberInt(1135241564), 
            "planh" : ""
        }, 

    ], 
    "leader_id" : "U08EC7FTM", 
    "checked" : true
}

四、数组里面包含内嵌文档的查询

这种查询相对来说比较复杂一点,所以内嵌文档的匹配也需要有些技巧。例如下面的博客文档中有一个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" } ]   
}  

如果当前查询有多个内嵌文档匹配,只会返回第一个

六、按照正则表达式查询内嵌文档某个字段包含某个字符串

举例:

{ 
    "_id" : "U08G7H48Y_2016-07-08", 
    "user_id" : "U08G7H48Y", 
    "date" : "2016-07-08", 
    "update_time" : NumberLong(1467978750), 
    "goals" : [
        {
            "status" : "unsure", 
            "user_id" : "U08G7H48Y", 
            "goal" : "价值目标:确保IA项目组盈利指标达标", 
            "assigner" : "", 
            "tool" : "", 
            "method_ok" : true, 
            "id" : NumberInt(1363999581), 
            "done_time" : NumberInt(0), 
            "reason" : "短期目标不能确保:找不到更好的拿新用户的方法", 
            "create_time" : NumberLong(1466508766869), 
            "criterion" : "确保每天收入达到5w,力争6w\nFollow:1w\nLike:1.5w\nTracker:0.5w\nPrivacy:1.5w\nMemoryBoost:1.5w", 
            "expire_time" : NumberInt(0), 
            "execution" : NumberInt(2), 
            "method" : "已经入思维导图。\n确保7月30日收入达到1.5w", 
            "planh" : ""
        }, 
        {
            "status" : "ensure", 
            "user_id" : "U08G7H48Y", 
            "goal" : "价值目标:确保给组员制造W-W局面", 
            "assigner" : "", 
            "tool" : "Wunderlist", 
            "method_ok" : true, 
            "id" : NumberLong(2633899071), 
            "done_time" : NumberInt(0), 
            "reason" : "", 
            "create_time" : NumberLong(1465283369329), 
            "criterion" : "帮助管理者(李丁,时迁,贾博,卢燕涛,孟友阳)盯住他的组员", 
            "expire_time" : NumberInt(0), 
            "execution" : NumberInt(1), 
            "method" : "确保增加项目负责人的管理组员能力:\n李丁每两周跟我Review一下他的组员:需要设置李丁的ToDo\n时迁每两周跟我Review一下他的组员:需要设置时迁的ToDo\n卢燕涛每两周跟我Review一下他的组员:需要设置卢燕涛的ToDo\n孟友阳每周跟我Review一下他的组员:需要设置孟友阳的ToDo\n\n确保跟每个PM每个季度至少聊天一次: 已设置Review聊天记录的todo", 
            "planh" : ""
        }, 
        {
            "status" : "unsure", 
            "user_id" : "U08G7H48Y", 
            "goal" : "价值目标:确保PM可以流动起来", 
            "assigner" : "", 
            "tool" : "", 
            "method_ok" : true, 
            "id" : NumberInt(602193464), 
            "done_time" : NumberInt(0), 
            "reason" : "最近入职PM比较难,感觉流动这个目标会看不住", 
            "create_time" : NumberLong(1465284005711), 
            "criterion" : "确保组内PM新老搭配合理\n确保组内新PM快速培训", 
            "expire_time" : NumberInt(0), 
            "execution" : 1.5, 
            "method" : "确保7月底之前输入两个pm", 
            "planh" : ""
        }, 
        {
            "status" : "ensure", 
            "user_id" : "U08G7H48Y", 
            "goal" : "价值目标:确保项目组流程完善", 
            "assigner" : "", 
            "tool" : "", 
            "method_ok" : true, 
            "id" : NumberInt(1616685108), 
            "done_time" : NumberInt(0), 
            "reason" : "", 
            "create_time" : NumberLong(1465284199829), 
            "criterion" : "确保项目组DEV流程完善", 
            "expire_time" : NumberInt(0), 
            "execution" : 1.5, 
            "method" : "确保项目组DEV流程完善", 
            "planh" : ""
        }, 
        {
            "status" : "unsure", 
            "user_id" : "U08G7H48Y", 
            "goal" : "价值目标:确保项目组执行力达到1X", 
            "assigner" : "", 
            "tool" : "", 
            "method_ok" : false, 
            "id" : NumberLong(4283629091), 
            "done_time" : NumberInt(0), 
            "reason" : "暂时没有找到好的方法确保这个目标", 
            "create_time" : NumberLong(1465284143431), 
            "criterion" : "MB每周提交一个版本\nPM每周提交一个版本\niOS每两完成一个Feature", 
            "expire_time" : NumberInt(0), 
            "execution" : NumberInt(2), 
            "method" : "每个单子Archive的时候要想一些是否需要rethink", 
            "planh" : ""
        }, 
        {
            "status" : "ensure", 
            "user_id" : "U08G7H48Y", 
            "goal" : "价值目标:确保盯住竞争对手的程序", 
            "assigner" : "", 
            "tool" : "Wunderlist", 
            "method_ok" : true, 
            "id" : NumberLong(3852562557), 
            "done_time" : NumberInt(0), 
            "reason" : "", 
            "create_time" : NumberLong(1465283982245), 
            "criterion" : "确保看榜单,Like,Tracker等竞品", 
            "expire_time" : NumberInt(0), 
            "execution" : 1.5, 
            "method" : "确保每", 
            "planh" : ""
        }, 
        {
            "status" : "ensure", 
            "user_id" : "U08G7H48Y", 
            "goal" : "焦点目标", 
            "assigner" : "", 
            "tool" : "Wunderlist", 
            "method_ok" : true, 
            "id" : NumberInt(1973727620), 
            "done_time" : NumberInt(0), 
            "reason" : "", 
            "create_time" : NumberLong(1465284255588), 
            "criterion" : "确保关键字推广在持续推进", 
            "expire_time" : NumberInt(1469808000), 
            "execution" : 1.5, 
            "method" : "推广ROI", 
            "planh" : ""
        }, 
        {
            "status" : "unsure", 
            "user_id" : "U08G7H48Y", 
            "goal" : "焦点目标:确保", 
            "assigner" : "", 
            "tool" : "", 
            "method_ok" : true, 
            "id" : NumberInt(123662851), 
            "done_time" : NumberInt(0), 
            "reason" : "这周上线的时候。", 
            "create_time" : NumberLong(1465278975537), 
            "criterion" : "交叉", 
            "expire_time" : NumberInt(1467216000), 
            "execution" : NumberInt(2), 
            "method" : "详见思维导图", 
            "planh" : ""
        }, 
        {
            "status" : "ensure", 
            "user_id" : "U08G7H48Y", 
            "goal" : "焦点目标:确保跟进产品需求,多跟PM讨论各种产品需求", 
            "assigner" : "", 
            "tool" : "", 
            "method_ok" : true, 
            "id" : NumberLong(3918152115), 
            "done_time" : NumberInt(0), 
            "reason" : "", 
            "create_time" : NumberLong(1467335980569), 
            "criterion" : "确保每天至少找一个PM讨论需求15分钟\n确保每次产品需求评审会都参加", 
            "expire_time" : NumberInt(0), 
            "execution" : NumberInt(2), 
            "method" : "每天至少找一个PM讨论需求15分钟,已经入todo\n", 
            "planh" : ""
        }
    ], 
    "leader_id" : "U06UGFL12", 
    "comment" : "个人产品能力和", 
    "check_time" : NumberLong(1468158420)
}

mongo 原生代码查询

db.getCollection("goal_report").find({"goals":{"$elemMatch":{"goal":{"$regex":/价值目标/}}}})

mongoengine 查询

GoalReportMongoModel.objects(__raw__={"goals":{"$elemMatch":{"goal":{"$regex":'价值目标'}}}})

七、 查询数组

数组元素模糊匹配

数组字段badges每个包含该元素black的文档都将被返回

db.users.find({badges:"black"},{"_id":1,badges:1})
# 结果
        { "_id" : 1, "badges" : [ "blue", "black" ] }
        { "_id" : 4, "badges" : [ "red", "black" ] }
        { "_id" : 6, "badges" : [ "black", "blue" ] }
数组元素精确(全)匹配

数组字段badges的值为["black","blue"]的文档才能被返回(数组元素值和元素顺序全匹配)

 db.users.find({badges:["black","blue"]},{"_id":1,badges:1})
#结果
        { "_id" : 6, "badges" : [ "black", "blue" ] }
数组内嵌文档查询

查询数组points内嵌文档键points的值小于等于55的文档,此处通过.成员的方式实现

db.users.find( { 'points.points': { $lte: 55}},{"_id":1,points:1})
# 结果
        { "_id" : 3, "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
        { "_id" : 4, "points" : [ { "points" : 53, "bonus" : 15 }, { "points" : 51, "bonus" : 15 } ] }

你可能感兴趣的:(MongoDB查询内嵌文档)