本文僅僅學習使用,轉自:https://www.cnblogs.com/suoning/p/6759367.html#3682005
里面新增了如果用用Python代碼進行增刪改查
什么是MongoDB ?
MongoDB 是由C++語言編寫的,是一個基於分布式文件存儲的開源數據庫系統。
在高負載的情況下,添加更多的節點,可以保證服務器性能。
MongoDB 旨在為WEB應用提供可擴展的高性能數據存儲解決方案。
MongoDB 將數據存儲為一個文檔,數據結構由鍵值(key=>value)對組成。MongoDB 文檔類似於 JSON 對象。字段值可以包含其他文檔,數組及文檔數組。
主要特點
- MongoDB的提供了一個面向文檔存儲,操作起來比較簡單和容易。
- 你可以在MongoDB記錄中設置任何屬性的索引 (如:FirstName="Ning",Address="Beijing")來實現更快的排序。
- 你可以通過本地或者網絡創建數據鏡像,這使得MongoDB有更強的擴展性。
- 如果負載的增加(需要更多的存儲空間和更強的處理能力) ,它可以分布在計算機網絡中的其他節點上這就是所謂的分片。
- Mongo支持豐富的查詢表達式。查詢指令使用JSON形式的標記,可輕易查詢文檔中內嵌的對象及數組。
- MongoDb 使用update()命令可以實現替換完成的文檔(數據)或者一些指定的數據字段 。
- Mongodb中的Map/reduce主要是用來對數據進行批量處理和聚合操作。
- Map和Reduce。Map函數調用emit(key,value)遍歷集合中所有的記錄,將key與value傳給Reduce函數進行處理。
- Map函數和Reduce函數是使用Javascript編寫的,並可以通過db.runCommand或mapreduce命令來執行MapReduce操作。
- GridFS是MongoDB中的一個內置功能,可以用於存放大量小文件。
- MongoDB允許在服務端執行腳本,可以用Javascript編寫某個函數,直接在服務端執行,也可以把函數的定義存儲在服務端,下次直接調用即可。
- MongoDB支持各種編程語言:RUBY,PYTHON,JAVA,C++,PHP,C#等多種語言。
下載安裝配置啟動連接
官網:https://www.mongodb.com/download-center#community 下載對應系統的版本
linux系統的安裝:
curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.6.tgz # 下載 tar -zxvf mongodb-linux-x86_64-3.0.6.tgz # 解壓 mv mongodb-linux-x86_64-3.0.6/ /usr/local/mongodb # 將解壓包拷貝到指定目錄 export PATH=<mongodb-install-directory>/bin:$PATH #<mongodb-install-directory> 為Mongo的安裝路徑,如本文的 /usr/local/mongodb mkdir -p /data/db #創建數據庫目錄(啟動指定--dbpath)
wins安裝:
直接安裝,在安裝的過程中可能會有失敗的情況,注意把下面的勾去掉,然后下一步下一步就好了

Compass就是個數據庫管理工具,最早的時候沒有集成Compass, 最早的時候是用Robo 3T這個工具管理數據庫。
安裝不上Compass的時候,就可以用Root 3T.
MongoDB術語

配置文件
mac系統下的配置:
suoningdeMacBook-Pro:~ suoning$ cat /usr/local/etc/mongod.conf systemLog: destination: file path: /usr/local/var/log/mongodb/mongo.log logAppend: true storage: dbPath: /usr/local/var/mongodb net: bindIp: 127.0.0.1 port: 11811 suoningdeMacBook-Pro:~ suoning$
啟動
mac:
$ ./mongod $ ./mongod --dbpath=/data/db --rest # 默認端口為:27017 # MongoDB 提供了簡單的 HTTP 用戶界面。 如果你想啟用該功能,需要在啟動的時候指定參數 --rest # MongoDB 的 Web 界面訪問端口比服務的端口多1000。如果你的MongoDB運行端口使用默認的27017,
你可以在端口號為28017訪問web用戶界面,即地址為:http://localhost:28017
win:
啟動mongoDB 服務 cmd-> 進入安裝目錄的bin目錄,執行命令: mongod --dbpath=E:\Mongodata 其中: mongod:是啟動服務的.exe可執行文件 --dbpath=E:\Mongodata 配置的是將來數據的存儲目錄,需要實現創建好文件夾 E:\>E:\MongoDB\Server\4.0\bin\mongod --dbpath=E:\Mongodata
服務啟動成功后出現:等待鏈接的提示就說明服務啟動成功了

連接
要能夠連接成功的前提就是要開啟服務
mac:
$ sudo mongo $ sudo mongo --port 11811 $ sudo mongo -u root -p pwd 127.0.0.1:11811/test
win:可以通過Roob 3T來連接

安裝pymongo
目的是要在Python里使用,所以接下來安裝python插件,在cmd里安裝,執行下面的命令即可
pip install pymongo
在Python里連接MongoDB
1. 如何使用Python代碼去連接Mongo數據庫
2. 通過代碼操作:增
# 1. 導入MongoClient from pymongo import MongoClient # 首先,需要一個類,把對數據庫的增刪改查操作封裝為一個接口 # 該類的名名字隨便期 class Mongo(object): # 初始化,就是連接數據庫 # port:必須是個整數,不能加引號變成字符串 def __init__(self,host='localhost',port=27017): self.client = MongoClient(host,port) # 插入數據 def inert(self,database,collection,document): """ :param database: 表示哪個數據庫 :param collection: 表示哪個表 :param document: 表示哪個記錄 :return: """ # 1. 連接數據庫 _database = self.client.get_database(database) # 2.連接該庫下面要操作的表 _collection = _database.get_collection(collection) # 給表里插入一條數據 result = _collection.insert_one(document) # 插入數據后,返回的是什么數據類型?數據是什么?下面打印出來看看 print(type(result)) # <class 'pymongo.results.InsertOneResult'> print(dir(result)) # ['_InsertOneResult__acknowledged', '_InsertOneResult__inserted_id', '_WriteResult__acknowledged', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '_raise_if_unacknowledged', 'acknowledged', 'inserted_id']
print(result) # <pymongo.results.InsertOneResult object at 0x033A4DF0> print(result.inserted_id) # 插入成功后返回的一個id print(result.acknowledged) # 判斷有沒有插入成功,成功True,失敗:False
def __del__(self): self.client.close() if __name__ == '__main__': mongo = Mongo() data = { # 如果指定了插入時的id值,就會用你指定的值,如果沒有指定id值,插入后就會自動有個ObjectId("5bb9bc6aa236ce29f4898035") '_id':'5bb9bcb1a236ce2f008933ad', "name": '小甜甜', "age": 26 } # 插入數據 # 'trade_center':要插入的庫,如果不存在,mongoDB會自動幫你創建這個庫 # 'users':表,如果不存在,MongoDB會自動幫你創建表 # data: 要插入到 trade_center庫下面的users表里的數據 mongo.inert('trade_center','users',data)
# 1. 導入MongoClient from pymongo import MongoClient # 導入 from pymongo.errors import DuplicateKeyError class Mongo(object): def __init__(self,host='localhost',port=27017): self.client = MongoClient(host,port) # 插入數據 def insert(self,database,collection,document): # 有時候插入數據時,會出現重復的情況,比如: # 自定義了id 且 表里已經有一個相同的id # 通過try...except ...處理掉異常 try: _database = self.client.get_database(database) _collection = _database.get_collection(collection) result = _collection.insert_one(document) # 如果插入成功就返回一個result.acknowledged return result.acknowledged except DuplicateKeyError: return False def __del__(self): self.client.close() if __name__ == '__main__': mongo = Mongo() data = { "name": '小甜甜', "age": 26, "Hobbit":['吃','喝','玩','樂'] } mongo.insert('trade_center','users',data)
# 1. 導入MongoClient from pymongo import MongoClient from pymongo.errors import DuplicateKeyError # insert_one()與insert_many()的主要區別是: 當一次要插入多條數據時,用insert_many(), 當一次只插入一條數據時,用insert_one() class Mongo(object): # 初始化,就是連接數據庫 # port:必須是個整數,不能加引號變成字符串 def __init__(self,host='localhost',port=27017): self.client = MongoClient(host,port) # 插入數據 def insert(self,database,collection,document): try: _database = self.client.get_database(database) _collection = _database.get_collection(collection) # 如果document 是個字典,說明就是一個值,就可以用insert_one() # isinstance:是python里的函數,判斷一個對象是個個字典,還是個列表 if isinstance(document,dict): result = _collection.insert_one(document) # 如果插入成功就返回一個result.acknowledged return result.acknowledged elif isinstance(document,list): result = _collection.insert_many(document) return result.acknowledged else: return False except DuplicateKeyError: return False def delete(self,database,collection,document): pass def update(self,database,collection,document): pass def search(self,database,collection,document): pass def __del__(self): self.client.close() if __name__ == '__main__': mongo = Mongo() data =[ { "name": '小臭臭', "age": 23, "Hobbit": ['吃', '玩'] }, { "name": '小美美', "age": 24, "Hobbit": ['喝', '樂'] }, { "name": '大寶', "age": 28, "Hobbit": [ '傻樂'] }, ] mongo.insert('trade_center','users',data)
3.通過代碼操作:查
# 1. 導入MongoClient from pymongo import MongoClient from pymongo.errors import DuplicateKeyError # 首先,需要一個類,把對數據庫的增刪改查操作封裝為一個接口 # 該類的名名字隨便期 class Mongo(object): # 初始化,就是連接數據庫 # port:必須是個整數,不能加引號變成字符串 def __init__(self,host='localhost',port=27017): self.client = MongoClient(host,port) def search(self, database, collection, filter): """ :param database: 數據庫 :param collection: 表 :param filter: 查詢條件,查詢條件必須是個字典 :return: """ # 同理:先獲取數據庫 # 再得到表 # 最后就可以用該表去查找了 _database = self.client.get_database(database) _collection = _database.get_collection(collection) # 把查詢結果轉化成列表 results = list(_collection.find(filter)) print(type(results)) # <class 'pymongo.cursor.Cursor'> print(dir(results)) print(results) # 將查詢結果return return results def __del__(self): self.client.close() if __name__ == '__main__': mongo = Mongo() # 定義查詢條件,查詢條件必須是個字典 # 像下面的寫法,是and的關系 filter={ "name":"小臭臭",
# 注意:查詢條件里,如果值是int等類型時,不能加“”,否則就會查不到數據,同理,刪除/更新也是一樣的 "age":23 } mongo.search('trade_center','users',filter)
# 1. 導入MongoClient from pymongo import MongoClient from pymongo.errors import DuplicateKeyError # 首先,需要一個類,把對數據庫的增刪改查操作封裝為一個接口 # 該類的名名字隨便期 class Mongo(object): # 初始化,就是連接數據庫 # port:必須是個整數,不能加引號變成字符串 def __init__(self,host='localhost',port=27017): self.client = MongoClient(host,port) # 插入數據 # def insert(self,database,collection,document): # try: # _database = self.client.get_database(database) # _collection = _database.get_collection(collection) # # 如果document 是個字典,說明就是一個值,就可以用insert_one() # # isinstance:是python里的函數,判斷一個對象是個個字典,還是個列表 # if isinstance(document,dict): # result = _collection.insert_one(document) # # 如果插入成功就返回一個result.acknowledged # return result.acknowledged # elif isinstance(document,list): # result = _collection.insert_many(document) # return result.acknowledged # else: # return False # except DuplicateKeyError: # return False def delete(self,database,collection,document): pass def update(self,database,collection,document): pass def search(self, database, collection, filter): """ :param database: 數據庫 :param collection: 表 :param filter: 查詢條件,查詢條件必須是個字典 :return: """ # 同理:先獲取數據庫 # 再得到表 # 最后就可以用該表去查找了 _database = self.client.get_database(database) _collection = _database.get_collection(collection) # 把查詢結果轉化成列表 results = list(_collection.find(filter)) print(type(results)) # <class 'pymongo.cursor.Cursor'> print(dir(results)) print(results) # 將查詢結果return return results def __del__(self): self.client.close() if __name__ == '__main__': mongo = Mongo() # 如果查詢條件需要嵌套,通過.的方式一級級嵌套到key就行 # 如:"qiantao.namer":"大智" filter={ "qiantao.namer":"大智" } mongo.search('trade_center','users',filter)
4.通過代碼操作:刪
# 1. 導入MongoClient from pymongo import MongoClient class Mongo(object): # 初始化,就是連接數據庫 # port:必須是個整數,不能加引號變成字符串 def __init__(self,host='localhost',port=27017): self.client = MongoClient(host,port) def delete(self, database, collection, filter): # filter: 刪除的條件 _database = self.client.get_database(database) _collection = _database.get_collection(collection) result = _collection.delete_many(filter) print(result.acknowledged) return result.acknowledged def __del__(self): self.client.close() if __name__ == '__main__': mongo = Mongo() # 刪除的條件,如果值是整數,不能加引號 filter={ "age":26 } mongo.delete('trade_center','users',filter)
5.通過代碼操作:改
# 1. 導入MongoClient from pymongo import MongoClient from pymongo.errors import DuplicateKeyError class Mongo(object): # 初始化,就是連接數據庫 # port:必須是個整數,不能加引號變成字符串 def __init__(self,host='localhost',port=27017): self.client = MongoClient(host,port) def update(self,database,collection,filter,document_to): _database = self.client.get_database(database) _collection = _database.get_collection(collection) # filiter: 更新的條件 # update:第二個參數:即是否要更新的數據。即用update去更新那些符合filter條件的數據 # 更新的操作:要更新的數據,首先是個字典,字典里面的格式為:{"$set":要更新的內容} result = _collection.update_many(filter,{"$set":document_to},upsert=True) if __name__ == '__main__': mongo = Mongo() # filter:條件 filter={ "name":"小臭臭" } # 要更新成的數據 document_to={ "name":"小臭臭", "age":10, "Hobbit":["拉","pao"] } mongo.update('trade_center','users',filter,document_to)
安全驗證
創建管理員
> use admin
switched to db admin
> db
admin
> db.createUser({user:'suoning',pwd:'123456',roles:[{role:'userAdminAnyDatabase',db:'admin'}]})
Successfully added user: {
"user" : "suoning",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
> exit
bye
修改配置文件
版本區別與更多配置:https://docs.mongodb.com/manual/administration/configuration/
suoningdeMacBook-Pro:~ suoning$ cat /usr/local/etc/mongod.conf systemLog: destination: file path: /usr/local/var/log/mongodb/mongo.log logAppend: true storage: dbPath: /usr/local/var/mongodb net: bindIp: 127.0.0.1 port: 11811 security: authorization: enabled suoningdeMacBook-Pro:~ suoning$
重啟驗證
>
> show dbs
2017-04-25T08:41:50.126+0800 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not authorized on admin to execute command { listDatabases: 1.0 }",
"code" : 13,
"codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:761:19
shellHelper@src/mongo/shell/utils.js:651:15
@(shellhelp2):1:1
>
> use admin
switched to db admin
> db.auth('suoning','123456')
1
> show dbs
admin 0.000GB
local 0.000GB
>
創建普通用戶
> use admin
switched to db admin
> db.auth('suoning','123456')
1
>
> use mydb
switched to db mydb
> db.createUser({user:'nick',pwd:'123456',roles:[{role:'readWrite',db:'mydb'}]})
Successfully added user: {
"user" : "nick",
"roles" : [
{
"role" : "readWrite",
"db" : "mydb"
}
]
}
>
> db.auth('nick','123456')
1
>
刪除用戶
> db.dropUser("nick")
true
查看所有存在用戶
> use admin
switched to db admin
> db.auth('suoning','123456')
1
> db.system.users.find()
{ "_id" : "admin.suoning", "user" : "suoning", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "XXW+MD0TENKSkzk0bM2EGw==", "storedKey" : "iIuv5DpGOksvaFpFOSnAIRSwh+w=", "serverKey" : "ZGA7/Lkjv+RJX3fNANQN9hgBUwY=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }
{ "_id" : "mydb.nick", "user" : "nick", "db" : "mydb", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "j71pQs/OR1eRtRa1IT80+w==", "storedKey" : "5hkHmU+FwdENDgGjV0wIbmTAOrQ=", "serverKey" : "Qs+c0gfGNUpwD/ZKgeOackzwNxI=" } }, "roles" : [ { "role" : "readWrite", "db" : "mydb" } ] }
>
總結:
- 創建超級管理員需要未開啟權限模式的情況下執行;
- 如果 MongoDB 開啟了權限模式,並且某一個數據庫沒有任何用戶時,在不驗證權限的情況下,可以創建一個用戶,當繼續創建第二個用戶時,會返回錯誤,若想繼續創建用戶則必須登錄;
- 用戶只能在用戶所在數據庫登錄,管理員需要通過admin認證后才能管理其他數據庫。
數據庫角色
- 內建的角色
- 數據庫用戶角色:read、readWrite;
- 數據庫管理角色:dbAdmin、dbOwner、userAdmin;
- 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
- 備份恢復角色:backup、restore;
- 所有數據庫角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
- 超級用戶角色:root // 這里還有幾個角色間接或直接提供了系統超級用戶的訪問(dbOwner 、userAdmin、userAdminAnyDatabase)
- 內部角色:__system
角色說明: Read:允許用戶讀取指定數據庫 readWrite:允許用戶讀寫指定數據庫 dbAdmin:允許用戶在指定數據庫中執行管理函數,如索引創建、刪除,查看統計或訪問system.profile userAdmin:允許用戶向system.users集合寫入,可以找指定數據庫里創建、刪除和管理用戶 clusterAdmin:只在admin數據庫中可用,賦予用戶所有分片和復制集相關函數的管理權限。 readAnyDatabase:只在admin數據庫中可用,賦予用戶所有數據庫的讀權限 readWriteAnyDatabase:只在admin數據庫中可用,賦予用戶所有數據庫的讀寫權限 userAdminAnyDatabase:只在admin數據庫中可用,賦予用戶所有數據庫的userAdmin權限 dbAdminAnyDatabase:只在admin數據庫中可用,賦予用戶所有數據庫的dbAdmin權限。 root:只在admin數據庫中可用。超級賬號,超級權限
數據類型
| 數據類型 | 描述 |
|---|---|
| String | 字符串。存儲數據常用的數據類型。在 MongoDB 中,UTF-8 編碼的字符串才是合法的。 |
| Integer | 整型數值。用於存儲數值。根據你所采用的服務器,可分為 32 位或 64 位。 |
| Boolean | 布爾值。用於存儲布爾值(真/假)。 |
| Double | 雙精度浮點值。用於存儲浮點值。 |
| Min/Max keys | 將一個值與 BSON(二進制的 JSON)元素的最低值和最高值相對比。 |
| Arrays | 用於將數組或列表或多個值存儲為一個鍵。 |
| Timestamp | 時間戳。記錄文檔修改或添加的具體時間。 |
| Object | 用於內嵌文檔。 |
| Null | 用於創建空值。 |
| Symbol | 符號。該數據類型基本上等同於字符串類型,但不同的是,它一般用於采用特殊符號類型的語言。 |
| Date | 日期時間。用 UNIX 時間格式來存儲當前日期或時間。你可以指定自己的日期時間:創建 Date 對象,傳入年月日信息。 |
| Object ID | 對象 ID。用於創建文檔的 ID。 |
| Binary Data | 二進制數據。用於存儲二進制數據。 |
| Code | 代碼類型。用於在文檔中存儲 JavaScript 代碼。 |
| Regular expression | 正則表達式類型。用於存儲正則表達式。 |
庫與表操作
創建庫與表
> show dbs
admin 0.000GB
local 0.000GB
>
> use mydb
switched to db mydb
> db
mydb
>
> db.mydb.insert({"name":"Nick","age":18})
WriteResult({ "nInserted" : 1 })
>
> show dbs
admin 0.000GB
local 0.000GB
mydb 0.000GB
>
> show tables;
mydb
>
刪除庫
> db.dropUser("nick")
true
>
> db.createUser({user:'nick',pwd:'123456',roles:[{role:'dbAdmin',db:'mydb'}]})
Successfully added user: {
"user" : "nick",
"roles" : [
{
"role" : "dbAdmin",
"db" : "mydb"
}
]
}
>
> db.auth("nick","123456")
1
>
> use mydb
switched to db mydb
> db
mydb
>
> show dbs;
admin 0.000GB
local 0.000GB
mydb 0.000GB
>
> db.dropDatabase()
{ "dropped" : "mydb", "ok" : 1 }
>
> show dbs;
admin 0.000GB
local 0.000GB
>
刪除表
> db; mydb > show tables; mydb > > db.mydb.drop(); true > show tables; >
文檔操作
增
使用 insert() 或 save() 方法向集合中插入文檔,語法如下:
db.COLLECTION_NAME.insert(document)
創建讀寫用戶:
> db.createUser({user:'ning',pwd:'123456',roles:[{role:'readWrite',db:'mydb'}]})
Successfully added user: {
"user" : "ning",
"roles" : [
{
"role" : "readWrite",
"db" : "mydb"
}
]
}
>
> db.auth('ning','123456')
1
>
插入數據:
>
> db.user.insert({'name':'nick','age':18,'girlfriend':['jenny','coco','julia']})
WriteResult({ "nInserted" : 1 })
>
> show tables
user
>
>
> vb = ({'sex':'man'});
{ "sex" : "man" }
> db.user.insert(vb);
WriteResult({ "nInserted" : 1 })
>
插入文檔你也可以使用 db.col.save(document) 命令。如果不指定 _id 字段 save() 方法類似於 insert() 方法。如果指定 _id 字段,則會更新該 _id 的數據。
刪
remove() 方法的基本語法格式如下所示:
db.collection.remove(
<query>,
<justOne>
)
# MongoDB 是 2.6 版本以后的,語法格式如下:
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
# 參數說明:
query :(可選)刪除的文檔的條件。
justOne : (可選)如果設為 true 或 1,則只刪除一個文檔。
writeConcern :(可選)拋出異常的級別。
刪除數據:
> db.user.find()
{ "_id" : ObjectId("58fef7d55b9ea92ab29fbd4b"), "name" : "nick", "age" : 18, "girlfriend" : [ "jenny", "coco", "julia" ] }
{ "_id" : ObjectId("58fef9165b9ea92ab29fbd4c"), "sex" : "man" }
>
> db.user.remove({'sex':'man'})
WriteResult({ "nRemoved" : 1 })
>
> db.user.find()
{ "_id" : ObjectId("58fef7d55b9ea92ab29fbd4b"), "name" : "nick", "age" : 18, "girlfriend" : [ "jenny", "coco", "julia" ] }
>
刪除第一條找到的記錄可以設置 justOne 為 1:
>db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)
刪除所有數據:
>db.col.remove({})
>db.col.find()
>
改
# 只更新一條
> db.user.find()
{ "_id" : ObjectId("58fef7d55b9ea92ab29fbd4b"), "name" : "nick", "age" : 21, "girlfriend" : [ "jenny", "coco", "julia" ] }
{ "_id" : ObjectId("58feffe55b9ea92ab29fbd4d"), "name" : "jenny", "age" : 21 }
>
> db.user.update({'age':21},{$set:{'age':22}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
> db.user.find()
{ "_id" : ObjectId("58fef7d55b9ea92ab29fbd4b"), "name" : "nick", "age" : 22, "girlfriend" : [ "jenny", "coco", "julia" ] }
{ "_id" : ObjectId("58feffe55b9ea92ab29fbd4d"), "name" : "jenny", "age" : 21 }
>
# 更新多條
> db.user.find()
{ "_id" : ObjectId("58fef7d55b9ea92ab29fbd4b"), "name" : "nick", "age" : 21, "girlfriend" : [ "jenny", "coco", "julia" ] }
{ "_id" : ObjectId("58feffe55b9ea92ab29fbd4d"), "name" : "jenny", "age" : 21 }
>
> db.user.update({'age':21},{$set:{'age':22}},{multi:true})
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
>
> db.user.find()
{ "_id" : ObjectId("58fef7d55b9ea92ab29fbd4b"), "name" : "nick", "age" : 22, "girlfriend" : [ "jenny", "coco", "julia" ] }
{ "_id" : ObjectId("58feffe55b9ea92ab29fbd4d"), "name" : "jenny", "age" : 22 }
>
save() 方法通過傳入的文檔來替換已有文檔。語法格式如下:
db.collection.save(
<document>,
{
writeConcern: <document>
}
)
參數說明:
document : 文檔數據。
writeConcern :可選,拋出異常的級別。
> db.user.find()
{ "_id" : ObjectId("58fef7d55b9ea92ab29fbd4b"), "name" : "nick", "age" : 22, "girlfriend" : [ "jenny", "coco", "julia" ] }
>
> db.user.save({ "_id" : ObjectId("58fef7d55b9ea92ab29fbd4b"), "name" : "nick", "age" : 18, "girlfriend" : [ "jenny", "julia" ] })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
> db.user.find().pretty()
{
"_id" : ObjectId("58fef7d55b9ea92ab29fbd4b"),
"name" : "nick",
"age" : 18,
"girlfriend" : [
"jenny",
"julia"
]
}
>
查
查詢數據的語法格式如下:
db.mydb.find(query, projection) query :可選,使用查詢操作符指定查詢條件 projection :可選,使用投影操作符指定返回的鍵。查詢時返回文檔中所有鍵值, 只需省略該參數即可(默認省略)。
pretty() 方法以格式化的方式來顯示所有文檔。 >db.mydb.find().pretty()
大於小於:
| 操作 | 格式 | 范例 | RDBMS中的類似語句 |
|---|---|---|---|
| 等於 | {<key>:<value>} |
db.col.find({"name":"nick"}).pretty() |
where name = 'nick' |
| 小於 | {<key>:{$lt:<value>}} |
db.col.find({"likes":{$lt:50}}).pretty() |
where likes < 50 |
| 小於或等於 | {<key>:{$lte:<value>}} |
db.col.find({"likes":{$lte:50}}).pretty() |
where likes <= 50 |
| 大於 | {<key>:{$gt:<value>}} |
db.col.find({"likes":{$gt:50}}).pretty() |
where likes > 50 |
| 大於或等於 | {<key>:{$gte:<value>}} |
db.col.find({"likes":{$gte:50}}).pretty() |
where likes >= 50 |
| 不等於 | {<key>:{$ne:<value>}} |
db.col.find({"likes":{$ne:50}}).pretty() |
where likes != 50 |
獲取"col"集合中 "likes" 大於100,小於 200 的數據,你可以使用以下命令:
db.col.find({likes : {$lt :200, $gt : 100}})
and or:
and:
>db.col.find({key1:value1, key2:value2}).pretty()
or:
>db.col.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
).pretty()
Limit、Skip
limit()方法基本語法如下所示:
>db.COLLECTION_NAME.find().limit(NUMBER)
skip() 方法腳本語法格式如下:
使用skip()方法來跳過指定數量的數據,skip方法接受一個數字參數作為跳過的記錄條數,默認為0。
>db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
sort
sort()方法對數據進行排序,sort()方法可以通過參數指定排序的字段,並使用 1 和 -1 來指定排序的方式,其中 1 為升序排列,而-1是用於降序排列。
>db.COLLECTION_NAME.find().sort({KEY:1})
操作符 $type
獲取 "col" 集合中 title 為 String 的數據:
db.col.find({"title" : {$type : 2}})
對應匹配類型:
| 類型 | 數字 | 備注 |
|---|---|---|
| Double | 1 | |
| String | 2 | |
| Object | 3 | |
| Array | 4 | |
| Binary data | 5 | |
| Undefined | 6 | 已廢棄。 |
| Object id | 7 | |
| Boolean | 8 | |
| Date | 9 | |
| Null | 10 | |
| Regular Expression | 11 | |
| JavaScript | 13 | |
| Symbol | 14 | |
| JavaScript (with scope) | 15 | |
| 32-bit integer | 16 | |
| Timestamp | 17 | |
| 64-bit integer | 18 | |
| Min key | 255 | Query with -1. |
| Max key | 127 |
索引
使用 ensureIndex() 方法來創建索引,語法如下:
>db.COLLECTION_NAME.ensureIndex({KEY:1})
語法中 Key 值為你要創建的索引字段,1為指定按升序創建索引,如果你想按降序來創建索引指定為-1即可
復合索引
db.col.ensureIndex({"title":1,"description":-1})
后台執行
通過在創建索引時加background:true 的選項,讓創建工作在后台執行
db.values.ensureIndex({open: 1, close: 1}, {background: true})
ensureIndex() 接收可選參數,可選參數列表如下:
| Parameter | Type | Description |
|---|---|---|
| background | Boolean | 建索引過程會阻塞其它數據庫操作,background可指定以后台方式創建索引,即增加 "background" 可選參數。 "background" 默認值為false。 |
| unique | Boolean | 建立的索引是否唯一。指定為true創建唯一索引。默認值為false. |
| name | string | 索引的名稱。如果未指定,MongoDB的通過連接索引的字段名和排序順序生成一個索引名稱。 |
| dropDups | Boolean | 在建立唯一索引時是否刪除重復記錄,指定 true 創建唯一索引。默認值為 false. |
| sparse | Boolean | 對文檔中不存在的字段數據不啟用索引;這個參數需要特別注意,如果設置為true的話,在索引字段中不會查詢出不包含對應字段的文檔.。默認值為 false. |
| expireAfterSeconds | integer | 指定一個以秒為單位的數值,完成 TTL設定,設定集合的生存時間。 |
| v | index version | 索引的版本號。默認的索引版本取決於mongod創建索引時運行的版本。 |
| weights | document | 索引權重值,數值在 1 到 99,999 之間,表示該索引相對於其他索引字段的得分權重。 |
| default_language | string | 對於文本索引,該參數決定了停用詞及詞干和詞器的規則的列表。 默認為英語 |
| language_override | string | 對於文本索引,該參數指定了包含在文檔中的字段名,語言覆蓋默認的language,默認值為 language. |
索引不能被以下的查詢使用:
- 正則表達式及非操作符,如 $nin, $not, 等。
- 算術運算符,如 $mod, 等。
- $where 子句
最大范圍
- 集合中索引不能超過64個
- 索引名的長度不能超過125個字符
- 一個復合索引最多可以有31個字段
- 現有的索引字段的值超過索引鍵的限制,MongoDB中不會創建索引。
聚合
聚合(aggregate)主要用於處理數據(諸如統計平均值,求和等),並返回計算后的數據結果。
聚合的方法使用aggregate()方法,基本語法格式如下所示:
>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
以上實例類似sql語句: select by_user, count(*) from mycol group by by_user
我們通過字段by_user字段對數據進行分組,並計算by_user字段相同值的總和。
| 表達式 | 描述 | 實例 |
|---|---|---|
| $sum | 計算總和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
| $avg | 計算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
| $min | 獲取集合中所有文檔對應值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
| $max | 獲取集合中所有文檔對應值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
| $push | 在結果文檔中插入值到一個數組中。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
| $addToSet | 在結果文檔中插入值到一個數組中,但不創建副本。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
| $first | 根據資源文檔的排序獲取第一個文檔數據。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
| $last | 根據資源文檔的排序獲取最后一個文檔數據 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
管道
MongoDB的聚合管道將MongoDB文檔在一個管道處理完畢后將結果傳遞給下一個管道處理。管道操作是可以重復的。
表達式:處理輸入文檔並輸出。表達式是無狀態的,只能用於計算當前聚合管道的文檔,不能處理其它的文檔。
- $project:修改輸入文檔的結構。可以用來重命名、增加或刪除域,也可以用於創建計算結果以及嵌套文檔。
- $match:用於過濾數據,只輸出符合條件的文檔。$match使用MongoDB的標准查詢操作。
- $limit:用來限制MongoDB聚合管道返回的文檔數。
- $skip:在聚合管道中跳過指定數量的文檔,並返回余下的文檔。
- $unwind:將文檔中的某一個數組類型字段拆分成多條,每條包含數組中的一個值。
- $group:將集合中的文檔分組,可用於統計結果。
- $sort:將輸入文檔排序后輸出。
- $geoNear:輸出接近某一地理位置的有序文檔。
管道操作符實例
1、$project實例
db.article.aggregate(
{ $project : {
title : 1 ,
author : 1 ,
}}
);
這樣的話結果中就只還有_id,tilte和author三個字段了,默認情況下_id字段是被包含的,如果要想不包含_id話可以這樣:
db.article.aggregate(
{ $project : {
_id : 0 ,
title : 1 ,
author : 1
}});
2.$match實例
db.articles.aggregate( [
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );
$match用於獲取分數大於70小於或等於90記錄,然后將符合條件的記錄送到下一階段$group管道操作符進行處理。
3.$skip實例
db.article.aggregate(
{ $skip : 5 });
經過$skip管道操作符處理后,前五個文檔被"過濾"掉。
查詢分析
explain()
mongo執行計划分析,詳細點此處。
> db.user.find({"name":"nick"}).explain();
> db.user.find({"name":"nick"}).explain(true);
關鍵參數詳細:
executionStats.executionSuccess 是否執行成功 executionStats.nReturned 查詢的返回條數 executionStats.executionTimeMillis 整體執行時間 executionStats.totalKeysExamined 索引掃描次數 executionStats.totalDocsExamined document掃描次數
hint()
使用 hint 來強制 MongoDB 使用一個指定的索引。
這種方法某些情形下會提升性能。 一個有索引的 collection 並且執行一個多字段的查詢(一些字段已經索引了)。
如下查詢指定了使用 naem 和 age 索引字段來查詢:
> db.user.find({"name":"nick","age":18}).hint({"name":1,"age":1});
