連接數(shù)據(jù)庫
MongoClient VS Connection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class MongoClient(pymongo.common.BaseObject) | Connection to MongoDB. | | Method resolution order: | MongoClient | pymongo.common.BaseObject | __builtin__. object | class Connection(pymongo.mongo_client.MongoClient) | Connection to MongoDB. | | Method resolution order: | Connection | pymongo.mongo_client.MongoClient | pymongo.common.BaseObject | __builtin__. object |
從這兩個(gè)類的繼承來看,connection是繼承了MongoClient的,建議使用MongoClient而不是使用Connection。(也就是說,MongoClient可以使用方法Connection都可以使用)
1
2
3
4
5
|
from pymongo import MongoClient client = MongoClient( '192.168.40.87' , 27037 ) db_name = 'TCL_Useraction' db = client[db_name] collection_useraction = db[ 'useraction' ] |
這里是通過字典的方式訪問數(shù)據(jù)庫和集合,同時(shí)你也可以通過.(點(diǎn)號(hào))的方式訪問
插入數(shù)據(jù)
save() VS insert()
mongodb的save和insert函數(shù)都可以向collection里插入數(shù)據(jù),但兩者是有兩個(gè)區(qū)別:
一、save函數(shù)實(shí)際就是根據(jù)參數(shù)條件,調(diào)用了insert或update函數(shù).如果想插入的數(shù)據(jù)對(duì)象存在,insert函數(shù)會(huì)報(bào)錯(cuò),而save函數(shù)是改變?cè)瓉淼膶?duì)象;如果想插入的對(duì)象不存在,那么它們執(zhí)行相同的插入操作.這里可以用幾個(gè)字來概括它們兩的區(qū)別,即所謂"有則改之,無則加之".
二、insert可以一次性插入一個(gè)列表,而不用遍歷,效率高, save則需要遍歷列表,一個(gè)個(gè)插入。
更新數(shù)據(jù)
對(duì)于單個(gè)數(shù)據(jù)來說,可以更新后使用save方法
update(criteria, objNew, upsert, mult)
criteria: 需要被更新的條件表達(dá)式
objNew: 更新表達(dá)式
upsert: 如目標(biāo)記錄不存在,是否插入新文檔。
multi: 是否更新多個(gè)文檔。
1
|
collection_useraction.update({ 'gid' :last_gid, 'time' :l_date}, { '$set' :{ 'gid' :last_gid}, '$set' :{ 'time' :l_date}, '$addToSet' :{ 'categories' :category_data}}, upsert = True ) |
刪除數(shù)據(jù)
1
2
3
4
5
6
7
8
9
|
db.users.drop() # 刪除集合 remove( self , spec_or_id = None , safe = None , multi = True , * * kwargs) # remove() 用于刪除單個(gè)或全部文檔,刪除后的文檔無法恢復(fù)。 id = db.users.find_one({ "name" : "user2" })[ "_id" ] db.users.remove( id ) # 根據(jù) id 刪除一條記錄 db.users.remove() # 刪除集合里的所有記錄 db.users.remove({ 'yy' : 5 }) # 刪除yy=5的記錄 |
查詢
5. 查詢
1
2
|
# 查詢 age 小于 15 的 for u in db.users.find({ "age" :{ "$lt" : 15 }}): print u |
5.1 查詢一條記錄
1
2
|
# 查詢 name 等于 user8 的 for u in db.users.find({ "name" : "user8" }): print u |
1
2
3
|
# 獲取查詢的一個(gè) u2 = db.users.find_one({ "name" : "user9" }) # 查不到時(shí)返回 None print u2 |
5.2 查詢特定鍵 (fields)
1
2
3
|
# select name, age from users where age = 21 for u in db.users.find({ "age" : 21 }, [ "name" , "age" ]): print u for u in db.users.find(fields = [ "name" , "age" ]): print u |
5.3 排序(SORT)
1
2
3
4
5
6
7
|
pymongo.ASCENDING # 也可以用 1 來代替 pymongo.DESCENDING # 也可以用 -1 來代替 for u in db.users.find().sort([( "age" , pymongo.ASCENDING)]): print u # select * from 集合名 order by 鍵1 for u in db.users.find().sort([( "age" , pymongo.DESCENDING)]): print u # select * from 集合名 order by 鍵1 desc for u in db.users.find().sort([( "鍵1" , pymongo.ASCENDING), ( "鍵2" , pymongo.DESCENDING)]): print u # select * from 集合名 order by 鍵1 asc, 鍵2 desc for u in db.users.find(sort = [( "鍵1" , pymongo.ASCENDING), ( "鍵2" , pymongo.DESCENDING)]): print u # sort 的另一種寫法 for u in db.users.find({ "name" : "user9" }, sort = [[ 'name' , 1 ],[ 'sex' , 1 ]], fields = [ "name" , "age" , 'sex' ]): print u # 組合寫法 |
5.4 從第幾行開始讀取(SLICE),讀取多少行(LIMIT)
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# select * from 集合名 skip 2 limit 3 # MySQL 的寫法: select * from 集合名 limit 2, 3 for u in db.users.find().skip( 2 ).limit( 3 ): print u for u in db.users.find(skip = 2 , limit = 3 ): print u # 可以用切片代替 skip & limit (mongo 中的 $slice 貌似有點(diǎn)問題)。 for u in db.users.find()[ 2 : 5 ]: print u # 單獨(dú)的寫 for u in db.users.find().skip( 2 ): print u for u in db.users.find(skip = 1 ): print u for u in db.users.find().limit( 5 ): print u for u in db.users.find(limit = 3 ): print u |
5.5 多條件查詢(Conditional Operators) # like 的可使用正則表達(dá)式查詢
1
2
3
4
|
# select * from users where name = 'user3' and age > 12 and age < 15 for u in db.users.find({ 'age' : { '$gt' : 12 , '$lt' : 15 }, 'name' : 'user3' }): print u # select * from users where name = 'user1' and age = 21 for u in db.users.find({ "age" : 21 , "name" : "user1" }): print u |
5.6 IN
1
2
|
for u in db.users.find({ "age" :{ "$in" :( 23 , 26 , 32 )}}): print u # select * from users where age in (23, 26, 32) for u in db.users.find({ "age" :{ "$nin" :( 23 , 26 , 32 )}}): print u # select * from users where age not in (23, 26, 32) |
5.7 統(tǒng)計(jì)總數(shù)(COUNT)
1
2
|
print (db.users.count()) # select count(*) from users print (db.users.find({ "age" :{ "$gt" : 30 }}).count()) # select count(*) from users where age > 30 |
5.8 OR
1
2
|
for u in db.users.find({ "$or" :[{ "age" : 25 }, { "age" : 28 }]}): print u # select * from 集合名 where 鍵1 = 值1 or 鍵1 = 值2 for u in db.users.find({ "$or" :[{ "age" :{ "$lte" : 23 }}, { "age" :{ "$gte" : 33 }}]}): print u # select * from 集合名 where 鍵1 <= 值1 or 鍵1 >= 值2 |
6. 是否存在 (exists)
1
2
|
db.users.find({ 'sex' :{ '$exists' : True }}) # select * from 集合名 where exists 鍵1 db.users.find({ 'sex' :{ '$exists' : False }}) # select * from 集合名 where not exists 鍵1 |
7. 正則表達(dá)式查詢
1
|
for u in db.users.find({ "name" : { "$regex" : r "(?i)user[135]" }}, [ "name" ]): print u # 查詢出 name 為 user1, user3, user5 |
8. 多級(jí)路徑的元素值匹配
Document 采取 JSON-like 這種層級(jí)結(jié)構(gòu),因此我們可以直接用嵌入(Embed)代替?zhèn)鹘y(tǒng)關(guān)系型數(shù)據(jù)庫的關(guān)聯(lián)引用(Reference)。
MongoDB 支持以 "." 分割的 namespace 路徑,條件表達(dá)式中的多級(jí)路徑須用引號(hào)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
# 如果鍵里面包含數(shù)組,只需簡(jiǎn)單匹配數(shù)組屬性是否包含該元素即可查詢出來 db.集合名.find_one({ 'address' : "address1" }) # address 是個(gè)數(shù)組,匹配時(shí)僅需包含有即可 # 查詢結(jié)果如:{"_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1", "address" : ["address1", "address2"]} # 條件表達(dá)式中的多級(jí)路徑須用引號(hào),以 "." 分割 u = db.集合名.find_one({ "im.qq" : 12345678 }) # 查詢結(jié)果如:{"_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1", "im" : {"msn" : "[email protected]", "qq" : 12345678}} # 多級(jí)路徑的更新 db.集合名.update({ "im.qq" : 12345678 }, { '$set' :{ "im.qq" : 12345 }}) # 查詢包含特定鍵的 for u in db.users.find({ "im.qq" :{ '$exists' : True }}, { "im.qq" : 1 }): print u # 顯示如: { "_id" : ObjectId("4c479885089df9b53474170a"), "im" : { "qq" : 12345 } } for u in db.users.find({ 'data' : "abc" }): print u # 顯示如: { "_id" : ObjectId("4c47a481b48cde79c6780df5"), "name" : "user8", "data" : [ { "a" : 1, "b" : 10 }, 3, "abc" ] } for u in db.users.find({ 'data' :{ '$elemMatch' :{ 'a' : 1 , 'b' :{ '$gt' : 5 }}}}): print u # 顯示如: { "_id" : ObjectId("4c47a481b48cde79c6780df5"), "name" : "user8", "data" : [ { "a" : 1, "b" : 10 }, 3, "abc" ] } |
{data:"abc"} 僅簡(jiǎn)單匹配數(shù)組屬性是否包含該元素。$elemMatch 則可以處理更復(fù)雜的元素查找條件。當(dāng)然也可以寫成如下方式:
db.集合名.find({"data.a":1, "data.b":{'$gt':5}})
對(duì)數(shù)組, 還可以直接使用序號(hào)進(jìn)行操作:
db.集合名.find({"data.1":3}) # 序號(hào)從0開始
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 如集合的一列內(nèi)容 { "classifyid" : "test1" , "keyword" :[ { "name" : 'test1' , # 將修改此值為 test5 (數(shù)組下標(biāo)從0開始,下標(biāo)也是用點(diǎn)) "frequence" : 21 , }, { "name" : 'test2' , # 子表的查詢,會(huì)匹配到此值 "frequence" : 50 , }, ] } # 子表的修改(子表的其它內(nèi)容不變) db.集合名.update({ "classifyid" : "test1" }, { "$set" :{ "keyword.0.name" : 'test5' }}) # 子表的查詢 db.集合名.find({ "classifyid" : "test1" , "keyword.0.name" : "test2" }) |
操作
(1) $all: 判斷數(shù)組屬性是否包含全部條件。
1
2
3
4
5
|
db.users.insert({ 'name' : "user3" , 'data' :[ 1 , 2 , 3 , 4 , 5 , 6 , 7 ]}) db.users.insert({ 'name' : "user4" , 'data' :[ 1 , 2 , 3 ]}) for u in db.users.find({ 'data' :{ '$all' :[ 2 , 3 , 4 ]}}): print u # 顯示: { "_id" : ObjectId("4c47a133b48cde79c6780df0"), "name" : "user3", "data" : [ 1, 2, 3, 4, 5, 6, 7 ] } |
注意和 $in 的區(qū)別。$in 是檢查目標(biāo)屬性值是條件表達(dá)式中的一員,而 $all 則要求屬性值包含全部條件元素。
(2) $size: 匹配數(shù)組屬性元素?cái)?shù)量。
1
2
|
for u in db.users.find({ 'data' :{ '$size' : 3 }}): print u # 只顯示匹配此數(shù)組數(shù)量的: { "_id" : ObjectId("4c47a13bb48cde79c6780df1"), "name" : "user4", "data" : [ 1, 2, 3 ] } |
(3) $type: 判斷屬性類型。
1
2
|
for u in db.users.find({ 't' :{ '$type' : 1 }}): print u # 查詢數(shù)字類型的 for u in db.users.find({ 't' :{ '$type' : 2 }}): print u # 查詢字符串類型的 |
類型值:
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) $not: 取反,表示返回條件不成立的文檔。
似乎只能跟正則和 $mod 一起使用????
# 還不知如何使用
(5) $unset: 和 $set 相反,表示移除文檔屬性。
1
2
3
4
5
6
|
for u in db.users.find({ 'name' : "user1" }): print u # 顯示如: { "_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1", "age" : 15, "address" : [ "address1", "address2" ] } db.users.update({ 'name' : "user1" }, { '$unset' :{ 'address' : 1 , 'age' : 1 }}) for u in db.users.find({ 'name' : "user1" }): print u # 顯示如: { "_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1" } |
(6) $push: 和 $ pushAll 都是向數(shù)組屬性添加元素。# 好像兩者沒啥區(qū)別
1
2
3
4
5
6
7
8
9
10
|
for u in db.users.find({ 'name' : "user1" }): print u # 顯示如: { "_id" : ObjectId("4c479885089df9b53474170a"), "age" : 15, "name" : "user1" } db.users.update({ 'name' : "user1" }, { '$push' :{ 'data' : 1 }}) for u in db.users.find({ 'name' : "user1" }): print u # 顯示如: { "_id" : ObjectId("4c479885089df9b53474170a"), "age" : 15, "data" : [ 1 ], "name" : "user1" } db.users.update({ 'name' : "user1" }, { '$pushAll' :{ 'data' :[ 2 , 3 , 4 , 5 ]}}) for u in db.users.find({ 'name' : "user1" }): print u # 顯示如: { "_id" : ObjectId("4c479885089df9b53474170a"), "age" : 15, "data" : [ 1, 2, 3, 4, 5 ], "name" : "user1" } |
(7) $addToSet: 和 $push 類似,不過僅在該元素不存在時(shí)才添加 (Set 表示不重復(fù)元素集合)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
db.users.update({ 'name' : "user2" }, { '$unset' :{ 'data' : 1 }}) db.users.update({ 'name' : "user2" }, { '$addToSet' :{ 'data' : 1 }}) db.users.update({ 'name' : "user2" }, { '$addToSet' :{ 'data' : 1 }}) for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c479896089df9b53474170b"), "data" : [ 1 ], "name" : "user2" } db.users.update({ 'name' : "user2" }, { '$push' :{ 'data' : 1 }}) for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c479896089df9b53474170b"), "data" : [ 1, 1 ], "name" : "user2" } 要添加多個(gè)元素,使用 $each。 db.users.update({ 'name' : "user2" }, { '$addToSet' :{ 'data' :{ '$each' :[ 1 , 2 , 3 , 4 ]}}}) for u in db.users.find({ 'name' : "user2" }): print u # 顯示: {u'age': 12, u'_id': ObjectId('4c479896089df9b53474170b'), u'data': [1, 1, 2, 3, 4], u'name': u'user2'} # 貌似不會(huì)自動(dòng)刪除重復(fù) |
(8) $each 添加多個(gè)元素用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
db.users.update({ 'name' : "user2" }, { '$unset' :{ 'data' : 1 }}) db.users.update({ 'name' : "user2" }, { '$addToSet' :{ 'data' : 1 }}) for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c479896089df9b53474170b"), "data" : [ 1 ], "name" : "user2" } db.users.update({ 'name' : "user2" }, { '$addToSet' :{ 'data' :{ '$each' :[ 1 , 2 , 3 , 4 ]}}}) for u in db.users.find({ 'name' : "user2" }): print u # 顯示: {u'age': 12, u'_id': ObjectId('4c479896089df9b53474170b'), u'data': [1, 2, 3, 4], u'name': u'user2'} db.users.update({ 'name' : "user2" }, { '$addToSet' :{ 'data' :[ 1 , 2 , 3 , 4 ]}}) for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c479896089df9b53474170b"), "data" : [ 1, 2, 3, 4, [ 1, 2, 3, 4 ] ], "name" : "user2" } db.users.update({ 'name' : "user2" }, { '$unset' :{ 'data' : 1 }}) db.users.update({ 'name' : "user2" }, { '$addToSet' :{ 'data' :[ 1 , 2 , 3 , 4 ]}}) for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ [1, 2, 3, 4] ], "name" : "user2" } |
(9) $pop: 移除數(shù)組屬性的元素(按數(shù)組下標(biāo)移除),$pull 按值移除,$pullAll 移除所有符合提交的元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
db.users.update({ 'name' : "user2" }, { '$unset' :{ 'data' : 1 }}) db.users.update({ 'name' : "user2" }, { '$addToSet' :{ 'data' :{ '$each' :[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 2 , 3 ]}}}) for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 1, 2, 3, 4, 5, 6, 7, 2, 3 ], "name" : "user2" } db.users.update({ 'name' : "user2" }, { '$pop' :{ 'data' : 1 }}) # 移除最后一個(gè)元素 for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 1, 2, 3, 4, 5, 6, 7, 2 ], "name" : "user2" } db.users.update({ 'name' : "user2" }, { '$pop' :{ 'data' : - 1 }}) # 移除第一個(gè)元素 for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 2, 3, 4, 5, 6, 7, 2 ], "name" : "user2" } db.users.update({ 'name' : "user2" }, { '$pull' :{ 'data' : 2 }}) # 移除全部 2 for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 3, 4, 5, 6, 7 ], "name" : "user2" } db.users.update({ 'name' : "user2" }, { '$pullAll' :{ 'data' :[ 3 , 5 , 6 ]}}) # 移除 3,5,6 for u in db.users.find({ 'name' : "user2" }): print u # 顯示: { "_id" : ObjectId("4c47a133b48cde79c6780df0"), "data" : [ 4, 7 ], "name" : "user2" } |
(10) $where: 用 JS 代碼來代替有些丑陋的 $lt、$gt。
MongoDB 內(nèi)置了 Javascript Engine (SpiderMonkey)。可直接使用 JS Expression,甚至使用 JS Function 寫更復(fù)雜的 Code Block。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
db.users.remove() # 刪除集合里的所有記錄 for i in range ( 10 ): db.users.insert({ 'name' : "user" + str (i), 'age' :i}) for u in db.users.find(): print u # 顯示如下: { "_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 } 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' } # 使用自定義的 function, javascript語法的 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' } |