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 } ] }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容