一、概述
有兩種方法可以查詢內(nèi)嵌文檔:查詢整個文檔蔓同;針對鍵值對進行查詢镶摘。這兩種方式是不同的悴务,下面我通過例子進行分別說明渴析。
二梭稚、查詢整個文檔
例如:有如下文檔
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'})
這種查詢會去精確匹配整個內(nèi)嵌文檔
三箱玷、鍵值對查詢
我們一般在查詢時怨规,不會去匹配整個內(nèi)嵌文檔,通常只針對內(nèi)嵌文檔的特定鍵值去查詢锡足。怎么做波丰?
答:查詢文檔時,可以使用"."來表示進入內(nèi)嵌文檔舶得。
參考實例:
db.getCollection("goal_report").find({"goals.goal":'價值目標COO-1',"goals.assigner":'san.zhang'})
查詢結(jié)果
{
"_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
}
四掰烟、數(shù)組里面包含內(nèi)嵌文檔的查詢
這種查詢相對來說比較復雜一點,所以內(nèi)嵌文檔的匹配也需要有些技巧沐批。例如下面的博客文檔中有一個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"}
]
})
現(xiàn)在要查詢由ickes評論的且5分以上文章
- 不能使用db.blog.find({"comments":{"name":"ickes","score":{"$gt":5}})去查,因為內(nèi)嵌文檔的匹配是精確匹配九孩,必須要匹配完整的文檔先馆,而這個查詢不會匹配comment鍵
- 不能使用db.blog.find({"comments":{"name":"ickes","score":{ '$gt' : 5},"comment":"nice"}})去查,還是那句話躺彬,文檔的匹配時精確匹配煤墙,這里使用了$gt作為范圍梅惯,所以也查不到
- 不能使用db.blog.find({"comments.name":"ickes","comments.score":{"$gt":5}})去查,前面講查詢條件的時候說過仿野,查詢條件里面的鍵值對會解釋為AND,但是對于數(shù)組的內(nèi)嵌文檔他會解釋為OR的關系铣减,也就是說上面實際是這樣的comments.name:ickes或者comments.score":{"$gt":5},這明顯不行嗎!(注意如果內(nèi)嵌文檔不在數(shù)組中脚作,還是AND葫哗,所以我才把這個拿出來單獨討論)
那對于數(shù)組里面的內(nèi)嵌文檔到底怎么辦?應該這么辦球涛,如下所示
這里需要使用"$elemMatch"操作符魄梯,僅當這種時候才使用這個操作符
db.blog.find({"comments":{
"$elemMatch":{"name":"ickes","score":{"$gt":5}}
}})
五、返回與查詢條件相匹配的任意一個數(shù)組元素
我們可以使用"$slice"操作符進行數(shù)組元素返回限制宾符,但是當數(shù)組里面保存的是文檔的時候,我就想返回與我查詢條件相匹配的那個元素灭翔,其他的不要魏烫,怎么做?有技巧的哦肝箱!
文檔結(jié)構(gòu)如下:
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}--第二個參數(shù)是限制返回數(shù)據(jù)的哄褒,別看錯了,這是第二個參數(shù)
)
返回結(jié)果如下:僅返回與當前查詢條件相匹配的那個內(nèi)嵌文檔煌张。
{
"_id" : "B001",
"comments" : [ { "name" : "ickes", "score" : 6, "comment" : "nice" } ]
}
如果當前查詢有多個內(nèi)嵌文檔匹配呐赡,只會返回第一個
六、按照正則表達式查詢內(nèi)嵌文檔某個字段包含某個字符串
舉例:
{
"_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" : "已經(jīng)入思維導圖链嘀。\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" : "確保組內(nèi)PM新老搭配合理\n確保組內(nèi)新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" : "價值目標:確保項目組執(zhí)行力達到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" : "確保關鍵字推廣在持續(xù)推進",
"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" : "焦點目標:確保跟進產(chǎn)品需求,多跟PM討論各種產(chǎn)品需求",
"assigner" : "",
"tool" : "",
"method_ok" : true,
"id" : NumberLong(3918152115),
"done_time" : NumberInt(0),
"reason" : "",
"create_time" : NumberLong(1467335980569),
"criterion" : "確保每天至少找一個PM討論需求15分鐘\n確保每次產(chǎn)品需求評審會都參加",
"expire_time" : NumberInt(0),
"execution" : NumberInt(2),
"method" : "每天至少找一個PM討論需求15分鐘看杭,已經(jīng)入todo\n",
"planh" : ""
}
],
"leader_id" : "U06UGFL12",
"comment" : "個人產(chǎn)品能力和",
"check_time" : NumberLong(1468158420)
}
mongo 原生代碼查詢
db.getCollection("goal_report").find({"goals":{"$elemMatch":{"goal":{"$regex":/價值目標/}}}})
mongoengine 查詢
GoalReportMongoModel.objects(__raw__={"goals":{"$elemMatch":{"goal":{"$regex":'價值目標'}}}})
七忠藤、 查詢數(shù)組
數(shù)組元素模糊匹配
數(shù)組字段badges每個包含該元素black的文檔都將被返回
db.users.find({badges:"black"},{"_id":1,badges:1})
# 結(jié)果
{ "_id" : 1, "badges" : [ "blue", "black" ] }
{ "_id" : 4, "badges" : [ "red", "black" ] }
{ "_id" : 6, "badges" : [ "black", "blue" ] }
數(shù)組元素精確(全)匹配
數(shù)組字段badges的值為["black","blue"]的文檔才能被返回(數(shù)組元素值和元素順序全匹配)
db.users.find({badges:["black","blue"]},{"_id":1,badges:1})
#結(jié)果
{ "_id" : 6, "badges" : [ "black", "blue" ] }
數(shù)組內(nèi)嵌文檔查詢
查詢數(shù)組points內(nèi)嵌文檔鍵points的值小于等于55的文檔,此處通過.成員的方式實現(xiàn)
db.users.find( { 'points.points': { $lte: 55}},{"_id":1,points:1})
# 結(jié)果
{ "_id" : 3, "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
{ "_id" : 4, "points" : [ { "points" : 53, "bonus" : 15 }, { "points" : 51, "bonus" : 15 } ] }