1. 程式人生 > >絕好的MongoDB學習資料之三. Schema Design

絕好的MongoDB學習資料之三. Schema Design

1. Document-Oriented

MongoDB 是一種面向文件(document-oriented)的資料庫,其記憶體儲的是一種 JSON-like 結構化資料。儘管擁有和關係型資料庫 Database/Table 類似的的 DB/Collection 概念,但同一 Collection 內的 Document 可以擁有不同的屬性。

(注: 以下 > 提示符表示 mongo JS 程式碼,>>> 為 Python 程式碼)

> use blog
switched to db blog

> db.users.insert({name:"user1", age:15})
> db.users.insert({name:"user2", age:20, sex:1})

> db.users.find()
{ "_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1", "age" : 15 }
{ "_id" : ObjectId("4c479896089df9b53474170b"), "name" : "user2", "age" : 20, "sex" : 1 }

可以通過 $exists 判斷某個欄位是否存在。

> db.users.find({sex:{$exists:true}})
{ "_id" : ObjectId("4c479896089df9b53474170b"), "name" : "user2", "age" : 20, "sex" : 1 }

2. Embed vs. Reference

Document 採取 JSON-like 這種層級結構,因此我們可以直接用嵌入(Embed)代替傳統關係型資料庫的關聯引用(Reference)。

> u = db.users.findOne({name:"user1"})
{
        "_id" : ObjectId("4c479885089df9b53474170a"),
        "name" : "user1",
        "age" : 15
}

> u.address = ["address1", "address2"]
[ "address1", "address2" ]

> db.users.save(u)

> db.users.findOne({name:"user1"})
{
        "_id" : ObjectId("4c479885089df9b53474170a"),
        "name" : "user1",
        "age" : 15,
        "address" : [
                "address1",
                "address2"
        ]
}

> db.users.findOne({address:"address1"})
{
        "_id" : ObjectId("4c479885089df9b53474170a"),
        "name" : "user1",
        "age" : 15,
        "address" : [
                "address1",
                "address2"
        ]
}

MongoDB 支援以 "." 分割的 namespace 路徑,但需要注意 key 不能以 "$" 開頭,不能包含 "." 字元 (條件表示式中的多級路徑須用引號)。

> u = db.users.findOne({address:"address1"})
{
        "_id" : ObjectId("4c479885089df9b53474170a"),
        "name" : "user1",
        "age" : 15,
        "address" : [
                "address1",
                "address2"
        ]
}

> u.im = {msn:"
[email protected]
", qq:12345678} { "msn" : "[email protected]", "qq" : 12345678 } > db.users.save(u) > u = db.users.findOne({"im.qq":12345678}) { "_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1", "age" : 15, "address" : [ "address1", "address2" ], "im" : { "msn" : "[email protected]", "qq" : 12345678 } } > u.im.qq 12345678 > u.im.msn [email protected] > db.users.update({"im.qq":12345678}, {$set:{"im.qq":12345}}) > u = db.users.findOne({"im.qq":12345}) { "_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1", "age" : 15, "address" : [ "address1", "address2" ], "im" : { "msn" : "[email protected]", "qq" : 12345 } } > u = db.users.find({"im.qq":{$exists:true}}, {"im.qq":1}) { "_id" : ObjectId("4c479885089df9b53474170a"), "im" : { "qq" : 12345 } }

注意: 由於每篇文件都包含完整的 key 資料,因此使用盡可能短的 key 可以有效節省儲存空間。

3. Operator

(1) $all: 判斷陣列屬性是否包含全部條件。

> db.users.insert({name:"user3", data:[1,2,3,4,5,6,7]})
> db.users.insert({name:"user4", data:[1,2,3]})

> db.users.find({data:{$all:[2,3,4]}})
{ "_id" : ObjectId("4c47a133b48cde79c6780df0"), "name" : "user3", "data" : [ 1, 2, 3, 4, 5, 6, 7 ] }

注意和 $in 的區別。$in 是檢查目標屬性值是條件表示式中的一員,而 $all 則要求屬性值包含全部條件元素。

(2) $size: 匹配陣列屬性元素數量。

> db.users.insert({name:"user3", data:[1,2,3,4,5,6,7]})
> db.users.insert({name:"user4", data:[1,2,3]})

> db.users.find({data:{$size:3}})
{ "_id" : ObjectId("4c47a13bb48cde79c6780df1"), "name" : "user4", "data" : [ 1, 2, 3 ] }

(3) $type: 判斷屬性型別。

> db.users.insert({name:"user5", t:1})
> db.users.insert({name:"user6", t:1.34})
> db.users.insert({name:"user7", t:"abc"})

> db.users.find({t:{$type:1}})
{ "_id" : ObjectId("4c47a231b48cde79c6780df2"), "name" : "user5", "t" : 1 }
{ "_id" : ObjectId("4c47a23eb48cde79c6780df3"), "name" : "user6", "t" : 1.34 }

> db.users.find({t:{$type:2}})
{ "_id" : ObjectId("4c47a258b48cde79c6780df4"), "name" : "user7", "t" : "abc" }


型別值:

  • double:1
  • string: 2
  • object: 3
  • array: 4
  • binary data: 5
  • object id: 7
  • boolean: 8
  • date: 9
  • null: 10
  • regular expression: 11
  • javascript code: 13
  • symbol: 14
  • javascript code with scope: 15
  • 32-bit integer: 16
  • timestamp: 17
  • 64-bit integer: 18
  • min key: 255
  • max key: 127
(4) 使用正則表示式進行查詢。
> db.users.find({name:/user[135]/i}, {name:1})
{ "_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1" }
{ "_id" : ObjectId("4c47a133b48cde79c6780df0"), "name" : "user3" }
{ "_id" : ObjectId("4c47a231b48cde79c6780df2"), "name" : "user5" }

>>> users = db.users.find({"name" : {"$regex" : r"(?i)user[135]"}}, ["name"])
>>> for u in users: print u
...
{u'_id': ObjectId('4c479885089df9b53474170a'), u'name': u'user1'}
{u'_id': ObjectId('4c47a133b48cde79c6780df0'), u'name': u'user3'}
{u'_id': ObjectId('4c47a231b48cde79c6780df2'), u'name': u'user5'}

正則表示式標記:

i: 忽略大小寫。
m: 預設為單行處理,此標記表示多行。
x: 擴充套件。

(5) 陣列屬性元素值匹配。

> db.users.find({data:"abc"})
{ "_id" : ObjectId("4c47a481b48cde79c6780df5"), "name" : "user8", "data" : [ { "a" : 1, "b" : 10 }, 3, "abc" ] }

> db.users.find({data:{$elemMatch:{a:1, b:{$gt:5}}}})
{ "_id" : ObjectId("4c47a481b48cde79c6780df5"), "name" : "user8", "data" : [ { "a" : 1, "b" : 10 }, 3, "abc" ] }

{data:"abc"} 僅簡單匹配陣列屬性是否包含該元素。$elemMatch 則可以處理更復雜的元素查詢條件。當然也可以寫成如下方式。

> db.users.find({"data.a":1, "data.b":{$gt:5}})
{ "_id" : ObjectId("4c47a481b48cde79c6780df5"), "name" : "user8", "data" : [ { "a" : 1, "b" : 10 }, 3, "abc" ] }

還可以直接使用序號進行操作。

> db.users.find({"data.2":3})
{ "_id" : ObjectId("4c47a133b48cde79c6780df0"), "name" : "user3", "data" : [ 1, 2, 3, 4, 5, 6, 7 ] }
{ "_id" : ObjectId("4c47a13bb48cde79c6780df1"), "name" : "user4", "data" : [ 1, 2, 3 ] }

(6) $not: 取反,表示返回條件不成立的文件。

似乎只能跟正則和 $mod 一起使用????

> u = db.users.find({name:{$not:/user3/}}, {name:1})
{ "_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1" }
{ "_id" : ObjectId("4c47a13bb48cde79c6780df1"), "name" : "user4" }
{ "_id" : ObjectId("4c47a231b48cde79c6780df2"), "name" : "user5" }
{ "_id" : ObjectId("4c47a23eb48cde79c6780df3"), "name" : "user6" }
{ "_id" : ObjectId("4c47a258b48cde79c6780df4"), "name" : "user7" }
{ "_id" : ObjectId("4c47a481b48cde79c6780df5"), "name" : "user8" }
{ "_id" : ObjectId("4c479896089df9b53474170b"), "name" : "user2" }

(7) $unset: 和 $set 相反,表示移除文件屬性。

> u = db.users.find({name:"user1"})
{ "_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1", "age" : 15, "address" : [ "address1", "address2" ], "im" : { "msn" : "[email protected]", "qq" : 12345 } }

> db.users.update({name:"user1"}, {$unset:{address:1, im:1}})

> u = db.users.find({name:"user1"})
{ "_id" : ObjectId("4c479885089df9b53474170a"), "age" : 15, "name" : "user1" }

(8) $push: 和 $ pushAll 都是向陣列屬性新增元素。

> u = db.users.find({name:"user1"})
{ "_id" : ObjectId("4c479885089df9b53474170a"), "age" : 15, "name" : "user1" }

> db.users.update({name:"user1"}, {$push:{data:1}})

> u = db.users.find({name:"user1"})
{ "_id" : ObjectId("4c479885089df9b53474170a"), "age" : 15, "data" : [ 1 ], "name" : "user1" }

> db.users.update({name:"user1"}, {$pushAll:{data:[2,3,4,5]}})

> u = db.users.find({name:"user1"})
{ "_id" : ObjectId("4c479885089df9b53474170a"), "age" : 15, "data" : [ 1, 2, 3, 4, 5 ], "name" : "user1" }

(9) $addToSet: 和 $push 類似,不過僅在該元素不存在時才新增 (Set 表示不重複元素集合)。

> db.users.update({name:"user2"}, {$addToSet:{data:1}})
> db.users.update({name:"user2"}, {$addToSet:{data:1}})

> u = db.users.find({name:"user2"})
{ "_id" : ObjectId("4c479896089df9b53474170b"), "data" : [ 1 ], "name" : "user2" }
> db.users.update({name:"user2"}, {$push:{data:1}})

> u = db.users.find({name:"user2"})
{ "_id" : ObjectId("4c479896089df9b53474170b"), "data" : [ 1, 1 ], "name" : "user2" }

要新增多個元素,使用 $each。

> db.users.update({name:"user2"}, {$addToSet:{data:{$each:[1,2,3,4]}}})

> u = db.users.find({name:"user2"})
{ "_id" : ObjectId("4c479896089df9b53474170b"), "data" : [ 1, 2, 3, 4 ], "name" : "user2" }

(10) $pop: 移除陣列屬性的元素,$pull 按值移除,$pullAll 移除所有符合提交的元素。

> u = db.users.find({name:"user3"})
{ "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 1, 2, 3, 4, 5, 6, 7, 2, 3 ], "name" : "user3" }

> db.users.update({name:"user3"}, {$pop:{data:1}}) // 移除最後一個元素

> u = db.users.find({name:"user3"})
{ "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 1, 2, 3, 4, 5, 6, 7, 2 ], "name" : "user3" }

> db.users.update({name:"user3"}, {$pop:{data:-1}}) // 移除第一個元素

> u = db.users.find({name:"user3"})
{ "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 2, 3, 4, 5, 6, 7, 2 ], "name" : "user3" }

> db.users.update({name:"user3"}, {$pull:{data:2}}) // 移除全部 2

> u = db.users.find({name:"user3"})
{ "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 3, 4, 5, 6, 7 ], "name" : "user3" }

> db.users.update({name:"user3"}, {$pullAll:{data:[4,5,6]}}) // 移除 4,5,6

> u = db.users.find({name:"user3"})
{ "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 3, 7 ], "name" : "user3" }

(11) $where: 用 JS 程式碼來代替有些醜陋的 $lt、$gt。

MongoDB 內建了 Javascript Engine (SpiderMonkey)。可直接使用 JS Expression,甚至使用 JS Function 寫更復雜的 Code Block。

> for (var i = 0; i < 10; i++) db.users.insert({name:"user"+i, age:i})

> db.users.find()
{ "_id" : ObjectId("4c47b3372a9b2be866da226e"), "name" : "user0", "age" : 0 }
{ "_id" : ObjectId("4c47b3372a9b2be866da226f"), "name" : "user1", "age" : 1 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2270"), "name" : "user2", "age" : 2 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2271"), "name" : "user3", "age" : 3 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2272"), "name" : "user4", "age" : 4 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2273"), "name" : "user5", "age" : 5 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2274"), "name" : "user6", "age" : 6 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2275"), "name" : "user7", "age" : 7 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2276"), "name" : "user8", "age" : 8 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2277"), "name" : "user9", "age" : 9 }

> db.users.find({$where:"this.age > 7 || this.age < 3"})
{ "_id" : ObjectId("4c47b3372a9b2be866da226e"), "name" : "user0", "age" : 0 }
{ "_id" : ObjectId("4c47b3372a9b2be866da226f"), "name" : "user1", "age" : 1 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2270"), "name" : "user2", "age" : 2 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2276"), "name" : "user8", "age" : 8 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2277"), "name" : "user9", "age" : 9 }

> db.users.find("this.age > 7 || this.age < 3")
{ "_id" : ObjectId("4c47b3372a9b2be866da226e"), "name" : "user0", "age" : 0 }
{ "_id" : ObjectId("4c47b3372a9b2be866da226f"), "name" : "user1", "age" : 1 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2270"), "name" : "user2", "age" : 2 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2276"), "name" : "user8", "age" : 8 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2277"), "name" : "user9", "age" : 9 }

> db.users.find({$where: function(){ return this.age > 7 || this.age < 3;}})
{ "_id" : ObjectId("4c47b3372a9b2be866da226e"), "name" : "user0", "age" : 0 }
{ "_id" : ObjectId("4c47b3372a9b2be866da226f"), "name" : "user1", "age" : 1 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2270"), "name" : "user2", "age" : 2 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2276"), "name" : "user8", "age" : 8 }
{ "_id" : ObjectId("4c47b3372a9b2be866da2277"), "name" : "user9", "age" : 9 }

>>> for u in db.users.find({"$where":"this.age > 7 || this.age < 3"}): print u
...
{u'age': 0.0, u'_id': ObjectId('4c47b3372a9b2be866da226e'), u'name': u'user0'}
{u'age': 1.0, u'_id': ObjectId('4c47b3372a9b2be866da226f'), u'name': u'user1'}
{u'age': 2.0, u'_id': ObjectId('4c47b3372a9b2be866da2270'), u'name': u'user2'}
{u'age': 8.0, u'_id': ObjectId('4c47b3372a9b2be866da2276'), u'name': u'user8'}
{u'age': 9.0, u'_id': ObjectId('4c47b3372a9b2be866da2277'), u'name': u'user9'}

>>> for u in db.users.find().where("this.age > 7 || this.age < 3"): print u
...
{u'age': 0.0, u'_id': ObjectId('4c47b3372a9b2be866da226e'), u'name': u'user0'}
{u'age': 1.0, u'_id': ObjectId('4c47b3372a9b2be866da226f'), u'name': u'user1'}
{u'age': 2.0, u'_id': ObjectId('4c47b3372a9b2be866da2270'), u'name': u'user2'}
{u'age': 8.0, u'_id': ObjectId('4c47b3372a9b2be866da2276'), u'name': u'user8'}
{u'age': 9.0, u'_id': ObjectId('4c47b3372a9b2be866da2277'), u'name': u'user9'}

>>> for u in db.users.find().where("function() { return this.age > 7 || this.age < 3;}"): print u
...
{u'age': 0.0, u'_id': ObjectId('4c47b3372a9b2be866da226e'), u'name': u'user0'}
{u'age': 1.0, u'_id': ObjectId('4c47b3372a9b2be866da226f'), u'name': u'user1'}
{u'age': 2.0, u'_id': ObjectId('4c47b3372a9b2be866da2270'), u'name': u'user2'}
{u'age': 8.0, u'_id': ObjectId('4c47b3372a9b2be866da2276'), u'name': u'user8'}
{u'age': 9.0, u'_id': ObjectId('4c47b3372a9b2be866da2277'), u'name': u'user9'}



相關推薦

MongoDB學習資料. Schema Design

1. Document-Oriented MongoDB 是一種面向文件(document-oriented)的資料庫,其記憶體儲的是一種 JSON-like 結構化資料。儘管擁有和關係型資料庫 Database/Table 類似的的 DB/Collection 概念,但同

ElasticSearch學習筆記十三 IK分詞器擴充套件字典及text全文型別資料分詞聚合查詢

ElasticSearch學習筆記之三十三 IK分詞器擴充套件字典及text全文型別資料分詞聚合查詢 專屬詞彙分詞失敗 擴充套件字典 檢視當前詞庫 自定義詞典 更新配置 再次檢視分詞 text全文型別資料分詞聚合

資料學習筆記十 Spark介紹之一

Spark簡介   主要用來加快資料分析的執行和讀寫速度   基於MapReduce演算法實現的分散式計算,在擁有Hadoop MapReduce所有優點的基礎上,其任務的中間結果還可以儲存在記憶體中,查詢速度快   處理迭代演算法(機器學習、圖挖掘演算法)和互動式資料探

IDL學習筆記 資料的輸入輸出與檔案讀寫

print,arr,format='(1i)';format控制輸出格式,eg:I02——int型,用0補全兩位輸出;I-   ——左對齊;讀取txt檔案的基本步驟:①獲取元資料②根據元資料建立一個空的陣列③定位到對應資料的位置,把裡面的陣列讀出來pro testreadtx

Vue.js 學習筆記:與伺服器的資料互動

顯而易見的,之前的`02_toDoList`存在著一個很致命的缺陷。那就是它的資料只存在於瀏覽器端,一但使用者關閉或重新載入頁面,他之前加入到程式中的資料就會全部丟失,一切又恢復到程式的初始狀態。要想解決這個問題,就需要 Web 應用的前端在適當的時間將獲得的輸入資料儲存到後端伺服器上,然後在需要時再從伺服器

x264學習資料——雷神博客系列

nag 視頻編碼器 category 雷神 -1 article nco spa gin 第一部分: http://blog.csdn.net/leixiaohua1020/article/category/2619503 FFmpeg與libx264接口源代碼簡單

MongoDB 學習筆記 權限管理基礎

顯示 命令 修改 技術 sky 需要 bad 官方 改密碼 權限管理基礎 MongoDB有很多用戶roles,這裏只是簡單列舉下命令的使用,具體的role的含義,請查閱官方文檔。 https://docs.mongodb.com/manual/reference/bui

MongoDB 學習筆記 分片和副本集混合運用

comment ssm table mmap insert ise class 學習 urn 分片和副本集混合運用: 基本架構圖: 搭建詳細配置: 3個shard + 3個replicat set + 3個configserver + 3個Mongos sh

MongoDB 學習筆記 手動預先分片

var http strong str 可見 mongod 手動 ++ 1-1 手動預先分片: 目的:手動預先分片是為了防止未來chunk的移動,減少IO。 sh.shardCollection("shop.users",{"userId": 1 }) for(v

MongoDB 學習筆記 TTL索引,部分索引和文本索引

強制 類型 支持 行存儲 pan 事件 搜索 篩選 ext TTL索引: TTL集合支持mongodb對存儲的數據進行失效時間設置,經過指定的時間段後、或在指定的時間點過期,集合自動被mongod清除。這一特性有利於對一些只需要保存一定時間的數據信息進行存儲,比如機器產生

MongoDB 學習筆記 地理空間索引入門

geometry 分享 如果 sphere mce insert del sap 計劃 地理空間索引: 地理空間索引,可用於處理基於地理位置的查詢。 Point:用於指定所在的具體位置,我們以restaurants為例: db.restaurants.insert({

MongoDB 學習筆記 $or與索引關系

其中 沒有 默認 ont mes exp style explain alt $or與索引關系: 對leftT集合的timestamp創建索引 執行$or語句:db.leftT.find({$or: [{ "timestamp" : 5},{"age": 10}]}

MongoDB 學習筆記 刪除數據,集合,數據庫

dia str .cn mongo 刪除數據 ron style god 學習 刪除數據,集合,數據庫: 刪除一個文檔: db.media.deleteOne({"name": "Sky"}) 刪除多個文檔: db.media.deleteMany({"name"

MongoDB 學習筆記 WriteConcern

行數據 num 部署 knowledge setting 其余 map not back WriteConcern: 轉載:MongoDB WriteConcern(寫關註)機制 http://www.ywnds.com/?p=3688&viewuser=40 Mo

Linux學習筆記————Linux命令概述

上下 eight ive 幫助 option pos misc tor tro 一、引言 很多人可能在電視或電影中看到過類似的場景,黑客面對一個黑色的屏幕,上面飄著密密麻麻的字符,梆梆一頓敲,就完成了竊取資料的任務。 Linux 剛出世時沒有什麽圖形界面,所有的操

Python學習日記 變量2、邏輯判斷、for循環

分享 奇怪 就是 inf bubuko 字母 for循環 判斷 發現 復習默寫猜數字小代碼,出現的問題。 While語句下的條件。應為result==false和answer=input()時。如果answer=input()寫在while的外邊,就會像昨天那樣一直輸出to

mongodb 學習基本操作

pretty 就是 log style 操作 16px 如果 -s collect 一、創建數據庫和表 在bin目錄下 執行 mongo 進入mongodb 建庫 use demo1 創建數據庫,芒果語法裏,use 表示,如果當前有這個數據庫就會使用, 如果沒喲就創

mongodb 學習安裝篇

過濾 div 路徑 日誌信息 創建 ssl mon 圖片 image 一、準備工作 源文件 mongodb-win32-x86_64-2008plus-ssl-3.4.10-signed.msi 安裝目錄 D:\mongodb 1. 創建幾個文件夾具體如下:數據庫路徑(da

MongoDB學習筆記Installing and Starting the Server

Mongodb1、創建YUM軟件倉庫 [root@hdp04 ~]# vi /etc/yum.repos.d/mongodb.repo [mongodb-org-3.6] name=MongoDB Repository baseurl=https://mirrors.aliyun.com/mongodb/y

dbms_lob包學習筆記:instr和substr存儲過程

hello 字節數 TE bms HERE substring 成功 其中 oracle instr和substr存儲過程,分析內部大對象的內容 instr函數與substr函數 instr函數用於從指定的位置開始,從大型對象中查找第N個與模式匹配