MongoDB进阶-内嵌文档查询
作為非關系型數據庫中的佼佼者,MongoDB一大優勢在于能夠在一條文檔中存儲對象類型的數據,適當增加冗余來讓數據庫更好用。文檔中一個對象類型的字段在MongoDB中被稱為內嵌文檔(Embedded),也是MongoDB推薦的存儲形式。本文將基于官方文檔介紹內嵌文檔的查詢方法。
1.內嵌文檔的適用場景
對于初創企業的技術團隊來說,快速變動的需求導致沒有必要花費過多精力設計關系嚴格的數據表,而是可以直接將相關聯的數據字段放在一起,比如以下設計:
db.books.insertMany( [{ _id: 1, name: "python", price: 25, size: { h: 14, w: 21}, reading: ["Tom","John"] },{ _id: 2, name: "mongo", price: 50, size: { h: 8.5, w: 11}, reading: ["John","Dave"] },{ _id: 3, name: "webGL", price: 80, size: { h: 8.5, w: 11}, reading: ["Lily"] }, ]); 復制代碼如果使用類似關系型數據主鍵的將_id作為引用的方式如下:
db.books.insertMany( [{ _id: 1, name: "python", price: 25, h: 14, w: 21, reading: ["Tom","John"] },{ _id: 2, name: "mongo", price: 50, h: 8.5, w: 11, reading: ["John","Dave"] },{ _id: 3, name: "webGL", price: 80, h: 8.5, w: 11, reading: ["Lily"] }, ]);db.reading.insertMany( [{ _id: 4, reader: "Tom", book_id:1 },{ _id: 5, reader: "John", book_id:1 },{ _id: 6, reader: "John", book_id:2 },{ _id: 7, reader: "Dave", book_id:2 },{ _id: 8, reader: "Lily", book_id:3 }, ]); 復制代碼相比之下,內嵌的方式有以下優點:
內嵌文檔可以降低字段修改對調用者的影響,比如在size字段下增加一個名為"l"的子字段表示書籍長度,對于調用者來說只需要在用到時從size對象中拿出來即可,不需要再去額外獲取新的字段。 因此,在內嵌文檔較小,更新頻率不高時推薦使用內嵌文檔來存儲數據。
2.內嵌文檔為字典的查詢方法
以1中數據為例,對于單值的字段查詢,只需要寫一個查詢字典(query filter)即可:
db.books.find( { price: 25 } ); 復制代碼當查詢條件涉及內嵌文檔中的子字段時,使用"."(可遞進使用):
db.books.find( { "size.h": 8.5 } );//針對字典對象-->[{ _id: 2, name: "mongo", price: 50, size: { h: 8.5, w: 11}, reading: ["John","Dave"] },{ _id: 3, name: "webGL", price: 80, size: { h: 8.5, w: 11}, reading: ["Lily"] },]db.books.find( { "reading.0": "Tom" } );//針對列表-->[{ _id: 1, name: "python", price: 25, h: 14, w: 21, reading: ["Tom","John"] },] 復制代碼注意,不使用"."的話將會嚴格匹配內嵌文檔:
db.books.find( { "size": { h: 8.5} } );//不存在size字段為{ h: 8.5}的文檔-->[] 復制代碼同普通查詢一樣,可以使用運算符Query Operator:
db.books.find( { "size.w": { $lt: 21} } );-->[{ _id: 2, name: "mongo", price: 50, size: { h: 8.5, w: 11}, reading: ["John","Dave"] },{ _id: 3, name: "webGL", price: 80, size: { h: 8.5, w: 11}, reading: ["Lily"] },] 復制代碼3.內嵌文檔為列表的查詢方法
示例數據
db.books.insertMany( [{ _id: 1, name: "python", price: 25, size: [14,21], reading: ["Tom","John"] },{ _id: 2, name: "mongo", price: 50, size: [8.5,11], reading: ["John","Dave"] },{ _id: 3, name: "webGL", price: 80, size: [8.5,11], reading: ["Lily"] }, ]); 復制代碼(1)指定列表{key:[value]} 列表必須符合value的條件
以1中數據為例,指定列表,將嚴格按照所有元素及其順序查詢:
db.books.find( { reading: ["Tom","John"]" });-->[{ _id: 1, name: "python", price: 25, size: size: [14,21], reading: ["Tom","John"] },] 復制代碼若只要求指定元素存在且不要求順序,使用$all:
db.books.find( { reading: { $all: ["John"] } });-->[{ _id: 1, name: "python", price: 25, size:[14,21], reading: ["Tom","John"] },{ _id: 2, name: "mongo", price: 50, size:[8.5,11], reading: ["John","Dave"] },] 復制代碼(2)指定元素{key:value1,value2...} 對于各個value的條件都至少有一個元素滿足即可,不要求一個元素同時滿足所有條件
db.books.find( { reading: "John" });//只要列表中有一元素的值為"John"即滿足-->[{ _id: 1, name: "python", price: 25, size:[14,21], reading: ["Tom","John"] },{ _id: 2, name: "mongo", price: 50, size:[8.5,11], reading: ["John","Dave"] },]db.books.find( { size: { $gt: 16, $lt: 15} });//只要列表中有一元素的值大于16,還有一元素小于15即滿足-->[{ _id: 1, name: "python", price: 25, size: [14,21], reading: ["Tom","John"] },] 復制代碼(3)指定元素{key:{$elemMatch:value1,value2...}} 只要至少有一元素同時符合各個value的條件
使用$elemMatch
db.books.find( { size: { $elemMatch: { $gt: 22, $lt: 30 } } });-->[{ _id: 1, name: "python", price: 25, size: [14,21], reading: ["Tom","John"] },] 復制代碼(4)指定列表長度{key:{ $size: value... }}滿足條件
使用$size
db.books.find( { reading: { $size: { $gt: 1} } });-->[{ _id: 3, name: "webGL", price: 80, size: [8.5,11], reading: ["Lily"] },] 復制代碼總結,對于列表類型的內嵌文檔,$elemMatch給出的并列條件要求至少有一個元素同時滿足,不使用elemMatch時并列的條件只需要各自至少有一個元素滿足即可。
轉載于:https://juejin.im/post/5ce3bd415188254d1528f015
總結
以上是生活随笔為你收集整理的MongoDB进阶-内嵌文档查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 新手入门 如何快速找到Python进阶路
- 下一篇: Spring注入方法