MongoDB快速入門(mén)

微信公眾號(hào):運(yùn)維開(kāi)發(fā)故事,作者:double冬

1 進(jìn)入MongoDB的世界

隨著大數(shù)據(jù)時(shí)代的到來(lái),數(shù)據(jù)急速增長(zhǎng),導(dǎo)致關(guān)系型數(shù)據(jù)庫(kù)(SQL)越來(lái)越不夠用。高性能、可擴(kuò)展的數(shù)據(jù)庫(kù)變得越來(lái)越重要起來(lái),在這樣的場(chǎng)景下,非關(guān)系型數(shù)據(jù)庫(kù)(NoSQL)應(yīng)運(yùn)而生,這里的“NoSQL”不是“NoSQL(不是SQL)”,而是“Not only SQL(不僅是SQL)”的簡(jiǎn)稱。2009年,分布式文檔型數(shù)據(jù)庫(kù)MongoDB引發(fā)了一場(chǎng)去SQL的浪潮。

1.1 非關(guān)系型數(shù)據(jù)庫(kù)的分類及特點(diǎn)非關(guān)系型數(shù)據(jù)庫(kù)主要分為以下幾類

  • 1.鍵值數(shù)據(jù)庫(kù)

主要代表是Redis、Flare。這類數(shù)據(jù)庫(kù)具有極高的讀寫(xiě)性能,用于處理大量數(shù)據(jù)的高訪問(wèn)負(fù)載比較合適。

  • 2.文檔型數(shù)據(jù)庫(kù)

主要代表是MongoDB、CouchDB。

這類數(shù)據(jù)庫(kù)滿足了海量數(shù)據(jù)的存儲(chǔ)和訪問(wèn)需求,同時(shí)對(duì)字段要求不嚴(yán)格,可以隨意地增加、刪除、修改字段,且不需要預(yù)先定義表結(jié)構(gòu),所以適用于各種網(wǎng)絡(luò)應(yīng)用。

  • 3.列存儲(chǔ)數(shù)據(jù)庫(kù)

主要代表是Cassandra、Hbase。這類數(shù)據(jù)庫(kù)查找速度快,可擴(kuò)展性強(qiáng),適合用作分布式文件存儲(chǔ)系統(tǒng)。

  • 4.圖數(shù)據(jù)庫(kù)

主要代表是InfoGrid、Neo4J。這類數(shù)據(jù)庫(kù)利用“圖結(jié)構(gòu)”的相關(guān)算法,適合用于構(gòu)建社交網(wǎng)絡(luò)和推薦系統(tǒng)的關(guān)系圖譜。

1.2 MongoDB適合做什么

MongoDB適合儲(chǔ)存大量關(guān)聯(lián)性不強(qiáng)的數(shù)據(jù)。MongoDB中的數(shù)據(jù)以“庫(kù)”—“集合”—“文檔”—“字段”結(jié)構(gòu)進(jìn)行儲(chǔ)存。這種結(jié)構(gòu)咋看和傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)的“庫(kù)”—“表”—“行”—“列”結(jié)構(gòu)非常像。但是,MongoDB不需要預(yù)先定義表結(jié)構(gòu),數(shù)據(jù)的字段可以任意變動(dòng),并發(fā)寫(xiě)入速度也遠(yuǎn)遠(yuǎn)超過(guò)傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)。

1.3 從文件到MongoDB數(shù)據(jù)庫(kù)

對(duì)于少量數(shù)據(jù),可以使用“記事本”程序來(lái)保存。但如果需要對(duì)數(shù)據(jù)進(jìn)行計(jì)算,那么記事本顯然就不能勝任了。此時(shí)可以考慮 Excel。還可以使用Excel 的數(shù)據(jù)透視表來(lái)統(tǒng)計(jì)數(shù)據(jù),如圖所示。

圖片

















Excel的一張表可以存放100萬(wàn)行左右的數(shù)據(jù),那如果每天的數(shù)據(jù)都超過(guò)100萬(wàn)行呢?此時(shí)就不得不使用數(shù)據(jù)庫(kù)來(lái)保存了。

使用MongoDB保存數(shù)據(jù)使用數(shù)據(jù)庫(kù),可以保存大量的數(shù)據(jù),這是數(shù)據(jù)庫(kù)最基本的功能。另外,數(shù)據(jù)庫(kù)還能夠?qū)?shù)據(jù)進(jìn)行邏輯運(yùn)算、數(shù)學(xué)運(yùn)算、搜索、批量修改或刪除。相比于傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù),MongoDB對(duì)于每一次插入的字段格式?jīng)]有要求,字段可以隨意變動(dòng),字段類型也可以隨意變動(dòng),如圖所示。

圖片

image.png

MongoDB可以并發(fā)插入上萬(wàn)條文檔,這是傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)所不能望其項(xiàng)背的。

2 MongoDB快速入門(mén)

會(huì)介紹MongoDB的安裝和基本語(yǔ)法。另外,介紹在圖形化管理工具Robo 3T中操作MongoDB,以及使用Python操作MongoDB的方法

MongoDB的語(yǔ)法與Python非常相似。在很多情況下,操作MongoDB的代碼都可以直接用到Python中。所以,結(jié)合Python來(lái)學(xué)習(xí)MongoDB可以起到事半功倍的效果

1.1 MongoDB和SQL術(shù)語(yǔ)對(duì)比

SQL與MongoDB術(shù)語(yǔ)對(duì)比見(jiàn)

SQLMongoDB
表(Table)集合(Collection)
行(Row)文檔(Document)
列(Col)字段(Field)
主鍵(Primary Key)對(duì)象ID(Objectid)
索引(Index)索引(Index)
嵌套表(Embeded Table)嵌入式文檔(Embeded Document)
數(shù)組(Array)數(shù)組(Array)

1.2 安裝MongoDB

1.2.1 在Windows中安裝

  • (1)訪問(wèn) MongoDB 官網(wǎng)的下載頁(yè)面(https://www.mongodb.com/download-center?jmp=nav#community),單擊“DOWNLOAD(msi)”按鈕。

圖片

image.png

  • (2)雙擊下載的文件(如無(wú)特殊說(shuō)明,只需要一直單擊“Next”按鈕即可)。在安裝過(guò)程中將會(huì)看到如圖所示的界面選擇安裝方式,這里單擊“Custom”按鈕。

圖片

image.png

圖片

image.png

  • (3)修改文件的安裝路徑到 D:\MongoDB\Server\,單擊“Next”按鈕進(jìn)行安裝,如圖所示。

圖片

image.png

  • (4)安裝完成以后,進(jìn)入D:\MongoDB\Server\4.2\bin,可以看到如圖所示的內(nèi)容,配置文件為mongod.cfg

圖片

image.png

  • (5)日志路徑為D:\MongoDB\Server\4.2\log

正常安裝完成之后,mongodb已經(jīng)注冊(cè)到服務(wù),并已正常運(yùn)行,后續(xù)的啟停都在這里管理

圖片

image.png

1.2.2 在Linux中安裝

由于 Linux 有眾多的發(fā)行版,不同發(fā)行版本有不同的包管理工具,所以在各個(gè)發(fā)行版本中安裝MongoDB的命令可能會(huì)有一些差異。本文以Centos7.6為例,來(lái)說(shuō)明如何安裝MongoDB。

1.配置MongoDB的yum源

創(chuàng)建yum源文件

添加以下內(nèi)容:(我們這里使用阿里云的源,安裝的是4.25版本)

[root@localhost ]# cd /etc/yum.repos.d
[root@localhost yum.repos.d]# vim mongodb-org-4.2.repo
[mngodb-org]
name=MongoDB Repository
baseurl=http://mirrors.aliyun.com/mongodb/yum/redhat/7Server/mongodb-org/4.2/x86_64/
gpgcheck=0
enabled=1

這里可以修改 gpgcheck=0, 省去gpg驗(yàn)證

安裝之前先更新所有包 :

[root@localhost yum.repos.d]# yum update
2.安裝MongoDB

安裝命令:

[root@localhost yum.repos.d]# yum -y install mongodb-org

安裝完成后

查看mongo安裝位置 whereis mongod

[root@localhost yum.repos.d]# whereis mongod
mongod: /usr/bin/mongod /etc/mongod.conf /usr/share/man/man1/mongod.1

查看修改配置文件 :vim /etc/mongod.conf

bindIp: 172.0.0.1 改為 bindIp: 0.0.0.0

(注意冒號(hào)與ip之間需要一個(gè)空格)

[root@localhost yum.repos.d]# cat /etc/mongod.conf
# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

# Where and how to store data.
storage:
  dbPath: /var/lib/mongo
  journal:
    enabled: true
#  engine:
#  wiredTiger:

# how the process runs
processManagement:
  fork: true  # fork and run in background
  pidFilePath: /var/run/mongodb/mongod.pid  # location of pidfile
  timeZoneInfo: /usr/share/zoneinfo

# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0  # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.


#security:

#operationProfiling:

#replication:

#sharding:

## Enterprise-Only Options

#auditLog:

#snmp:
3.啟動(dòng)MongoDB

啟動(dòng)mongodb :systemctl start mongod.service

停止mongodb :systemctl stop mongod.service

查到mongodb的狀態(tài):systemctl status mongod.service

設(shè)置開(kāi)啟自啟動(dòng):systemctl enable mongod.service

[root@localhost yum.repos.d]# systemctl status mongod.service
● mongod.service - MongoDB Database Server
   Loaded: loaded (/usr/lib/systemd/system/mongod.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2020-04-04 16:01:31 CST; 8s ago
     Docs: https://docs.mongodb.org/manual
  Process: 5492 ExecStart=/usr/bin/mongod $OPTIONS (code=exited, status=0/SUCCESS)
  Process: 5488 ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb (code=exited, status=0/SUCCESS)
  Process: 5485 ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb (code=exited, status=0/SUCCESS)
  Process: 5481 ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb (code=exited, status=0/SUCCESS)
 Main PID: 5495 (mongod)
   CGroup: /system.slice/mongod.service
           └─5495 /usr/bin/mongod -f /etc/mongod.conf

Apr 04 16:01:30 localhost.localdomain systemd[1]: Starting MongoDB Database Server...
Apr 04 16:01:30 localhost.localdomain mongod[5492]: about to fork child process, waiting until server is ready for connections.
Apr 04 16:01:30 localhost.localdomain mongod[5492]: forked process: 5495
Apr 04 16:01:31 localhost.localdomain mongod[5492]: child process started successfully, parent exiting
Apr 04 16:01:31 localhost.localdomain systemd[1]: Started MongoDB Database Server.
4.外網(wǎng)訪問(wèn)需要關(guān)閉防火墻

CentOS 7.0默認(rèn)使用的是firewall作為防火墻,這里改為iptables防火墻。

關(guān)閉firewall:

systemctl stop firewalld.service #停止firewall

systemctl disable firewalld.service #禁止firewall開(kāi)機(jī)啟動(dòng)

vim /etc/sysconfig/iptables

iptables文件添加

-A INPUT -m state --state NEW -m tcp -p tcp --dport 27017 -j ACCEPT

(注意:-A INPUT -m state --state NEW -m tcp -p tcp --dport 27017 -j ACCEPT要加在-A INPUT -j REJECT --reject-with icmp-host-prohibited之前,不然啟動(dòng)無(wú)效)

3 MongoDB的圖形化管理軟件——Robo 3T

MongoDB雖然自帶了一個(gè)終端環(huán)境下的客戶端,但是操作起來(lái)比較繁瑣,數(shù)據(jù)顯示也不夠直觀,因此需要使用一個(gè)圖形界面管理軟件來(lái)提高M(jìn)ongoDB數(shù)據(jù)的可讀性。

3.1 安裝

Robo 3T是一個(gè)跨平臺(tái)的MongoDB管理工具,采用圖形界面查詢或者修改MongoDB。Robo 3T的下載地址為:https://robomongo.org/download。在下載頁(yè)面中可以看到另一個(gè)叫作 Studio 3T 的軟件,它是一個(gè)功能更加強(qiáng)大的MongoDB圖形化管理軟件,但它是一個(gè)商業(yè)軟件,需要收費(fèi),而Robo 3T是開(kāi)源軟件并且免費(fèi),它的功能足夠應(yīng)付本書(shū)的所有應(yīng)用場(chǎng)景,因此本文選擇使用Robo 3T。

  • (1)安裝Robo 3T的安裝沒(méi)有任何需要特別說(shuō)明的地方,和安裝普通軟件一樣簡(jiǎn)單

圖片

image.png

  • (2)第一次成功啟動(dòng)Robot 3T時(shí),會(huì)看到一個(gè)用戶協(xié)議,如圖所示,勾選“我接受”按鈕

圖片

image.png

  • (3)選擇需要安裝的路徑,然后點(diǎn)擊安裝即可

  • (4)在下一個(gè)界面中添加名字公司之類的信息,可以直接忽略,單擊“完成”按鈕跳過(guò)即可






3.2 用Robo 3T連接MongoDB

  • (1)打開(kāi)Robo 3T,看到如圖所示對(duì)話框,單擊左上角“Create”鏈接。

圖片

image.png

  • (2)彈出如圖所示對(duì)話框。如果MongoDB就在本地電腦中運(yùn)行,則只需在“Name”欄中填寫(xiě)一個(gè)名字,其他地方不需要修改,然后直接單擊“Save”按鈕

圖片

image.png

  • (3)保存回到界面后,單擊“Connect”按鈕就可以連接MongoDB了

3.3 認(rèn)識(shí)Robo 3T的界面

Robo 3T的主界面如圖所示。重點(diǎn)關(guān)注A、B、C三個(gè)區(qū)域

圖片

image.png

  • 數(shù)據(jù)庫(kù)列表區(qū)(后簡(jiǎn)稱A區(qū)域),用于選擇數(shù)據(jù)庫(kù)和集合。

  • 數(shù)據(jù)展示區(qū)(后簡(jiǎn)稱B區(qū)域),用于顯示數(shù)據(jù)。

  • 命令執(zhí)行區(qū)(后簡(jiǎn)稱C區(qū)域),用于編寫(xiě)MongoDB代碼。

在A區(qū)域中,單擊數(shù)據(jù)庫(kù)圖標(biāo)左邊的箭頭,展開(kāi)數(shù)據(jù)庫(kù);單擊“Collections”左邊的箭頭,展開(kāi)集合。雙擊集合的名字,則B區(qū)域和C區(qū)域發(fā)生相應(yīng)的變化。

4 MongoDB的基本操作

增、查、改、刪是所有數(shù)據(jù)庫(kù)必備的功能。本節(jié)將介紹如何使用MongoDB 來(lái)實(shí)現(xiàn)這四個(gè)功能

4.1 創(chuàng)建數(shù)據(jù)庫(kù)與集合,寫(xiě)入數(shù)據(jù)

在Robo 3T中進(jìn)行如下操作:

  • (1)創(chuàng)建一個(gè)名為“chapter_1”的數(shù)據(jù)庫(kù),以及其中的多個(gè)集合

  • (2)往集合里逐條插入數(shù)據(jù)

  • (3)往集合里批量插入數(shù)據(jù)

使用Robo 3T打開(kāi)剛剛安裝完成的MongoDB,可以看到A區(qū)域是空的,還沒(méi)有數(shù)據(jù)庫(kù),如圖所示:

圖片

image.png

1.創(chuàng)建數(shù)據(jù)庫(kù)與集合

  • (1)鼠標(biāo)右擊“小電腦”圖標(biāo),在彈出的菜單中選擇“CreateDatabase”命令

  • (2)在彈出的對(duì)話框中輸入數(shù)據(jù)庫(kù)的名字,單擊“Create”按鈕完成數(shù)據(jù)庫(kù)的創(chuàng)建

圖片








  • (3)新創(chuàng)建的數(shù)據(jù)庫(kù)會(huì)出現(xiàn)在 A 區(qū)域中。單擊數(shù)據(jù)庫(kù)左邊的小箭頭將其展開(kāi),然后右擊“Collections(0)”文件夾,在彈出的菜單中選擇“Create Collection…”命令

  • (4)在彈出的對(duì)話框中輸入集合的名字,然后單擊“Create”按鈕,創(chuàng)建一個(gè)集合。

圖片








  • (5)創(chuàng)建完集合后,原來(lái)的“Collections(0)”變成了“Collections(1)”。由此可以推測(cè):括號(hào)里面的數(shù)字表示這個(gè)數(shù)據(jù)庫(kù)里面有多少個(gè)集合。單擊“Collections(1)”左側(cè)的小箭頭將其展開(kāi),可以看到集合“example_data_1”已經(jīng)創(chuàng)建好了。雙擊集合名字,可以看到當(dāng)前集合里什么都沒(méi)有,如圖所示:

圖片

image.png

2.插入單條數(shù)據(jù)

插入單條數(shù)據(jù)的命令為“insertOne()”,Robo 3T自帶插入數(shù)據(jù)的功能,但是在此不介紹了,本文會(huì)直接介紹如何在C區(qū)域執(zhí)行MongoDB命令插入數(shù)據(jù)。

(1)創(chuàng)建一條JSON字符串

例如:

{“name”: “王小二”, “age”: 17, “address”: “浙江”}

(2)對(duì)C區(qū)域的內(nèi)容做一些修改

原來(lái)是:

db.getCollection(‘example_data_1’).find({})

修改為:

db.getCollection(‘example_data_1’).insertOne({“name”: " 王小二 ",“age”: 17,“address”: “浙江”})

(3)使用Windows與Linux的讀者,可以按鍵盤(pán)上的“Ctrl + R”組合鍵,運(yùn)行后的界面如圖所示??梢钥吹剑粭l數(shù)據(jù)已經(jīng)插入到了MongoDB中

圖片

image.png

提示:還可以通過(guò)單擊Robo 3T上面的綠色三角形來(lái)運(yùn)行命令

  • (4)在 A 區(qū)域雙擊集合“example_data_1”,從新打開(kāi)的選項(xiàng)卡中可以看到數(shù)據(jù)已經(jīng)成功插入,如圖所示:

圖片

image.png

數(shù)據(jù)已經(jīng)成功插入被插入的數(shù)據(jù)就是JSON字符串:

{“name”: “張小二”, “age”: 17, “address”: “浙江”}

提示:JSON字符串必須使用雙引號(hào),不過(guò)這個(gè)規(guī)定在MongoDB中并非強(qiáng)制性的,用單引號(hào)也沒(méi)有問(wèn)題。例如,在C區(qū)域執(zhí)行以下命令:

db.getCollection(‘example_data_1’).insertOne({‘name’: ‘王小六’,‘a(chǎn)ge’: 23, ‘work’: ‘運(yùn)維工程師’})

如果將Python的字典直接復(fù)制到MongoDB的insertOne命令中,則絕大部分情況下這些字典都可以直接使用,只有極少數(shù)情況下需要做一些修改,后面會(huì)講到這些少數(shù)情況

提示:MongoDB還允許Key不帶引號(hào),直接寫(xiě)成

{name: ‘王小六’, age: 23,work: ‘運(yùn)維工程師’}

但這種寫(xiě)法存在一些局限性,并且會(huì)導(dǎo)致MongoDB的命令不方便平滑移植到Python中。因此,建議讀者一律使用帶單引號(hào)的寫(xiě)法或者帶雙引號(hào)的寫(xiě)法

3.調(diào)整插入的字段

  • (1)任意修改、添加、刪除字段。在現(xiàn)有的數(shù)據(jù)中,第1條數(shù)據(jù)沒(méi)有“work”這個(gè)字段,第2條數(shù)據(jù)沒(méi)有“address”這個(gè)字段。這就說(shuō)明:在MongoDB里,插入數(shù)據(jù)的字段是可以任意修改、添加、刪除的。例如,再插入一條新的數(shù)據(jù):
db.getCollection('example_data_1').insertOne({"hello": "world","sex": "男","職位": "程序員"})

這一次所有的字段都和前兩條數(shù)據(jù)不一樣,但 MongoDB 仍然可以輕松處理——遇到新來(lái)的字段,加上去就是了,沒(méi)什么大不了的,如圖所示:

圖片

image.png

  • (2)插入同一個(gè)字段,但格式卻不同,即使是同一個(gè)字段,其數(shù)據(jù)格式也可以不一樣

例如,再插入一條數(shù)據(jù):

db.getCollection('example_data_1').insertOne({"name": "1024","age": "十歲","address": "3.5"})

添加后的數(shù)據(jù)如圖所示:

圖片

image.png

提示:“能不能做”是一回事,“應(yīng)不應(yīng)該做”是另一回事。雖然MongoDB能夠處理同一個(gè)字段的不同數(shù)據(jù)類型,也可以隨意增減字段,但并不意味著應(yīng)該這樣做。在設(shè)計(jì)數(shù)據(jù)庫(kù)時(shí),應(yīng)盡量保證同一個(gè)字段使用同一種類型的數(shù)據(jù),并提前考慮好應(yīng)該有哪些字段。

3.批量插入數(shù)據(jù)

批量插入數(shù)據(jù)的命令是“insertMany”,把一個(gè)包含很多個(gè)字典的列表傳給“insertMany”。

列表為:

data_list = [
   {'name': '趙小三','age':20,'address':'北京'},
   {'name': '錢(qián)小四','age':21,'address':'上海'},
   {'name': '孫小五','age':20,'address':'山東'},
   {'name': '李小六','age':23,'address':'河北'},
   {'name': '歐陽(yáng)小七','age':24,'address':'杭州'},
]

對(duì)應(yīng)的MongoDB批量插入語(yǔ)句為:

db.getCollection('example_data_1').insertMany([
     {'name': '趙小三','age':20,'address':'北京'},
   {'name': '錢(qián)小四','age':21,'address':'上海'},
   {'name': '孫小五','age':20,'address':'山東'},
   {'name': '李小六','age':23,'address':'河北'},
   {'name': '歐陽(yáng)小七','age':24,'address':'杭州'}
 ])

運(yùn)行后返回的數(shù)據(jù)如圖所示:

圖片

image.png

提示:可以通過(guò)換行和縮進(jìn)讓代碼更美觀、易讀。換行和縮進(jìn)不影響代碼功能

運(yùn)行以后的集合數(shù)據(jù)如圖所示:

圖片

image.png

無(wú)論是插入一條數(shù)據(jù)還是插入多條數(shù)據(jù),每一條數(shù)據(jù)被插入 MongoDB后都會(huì)被自動(dòng)添加一個(gè)字段“_id”?!癬id”讀作“Object Id”,它是由時(shí)間、機(jī)器碼、進(jìn)程pid和自增計(jì)數(shù)器構(gòu)成的?!癬id”始終遞增,但絕不重復(fù)。

● 同一時(shí)間,不同機(jī)器上面的“_id”不同

● 同一機(jī)器,不同時(shí)間的“_id”也不同

● 同一機(jī)器同一時(shí)間批量插入的數(shù)據(jù),“_id”依然不同

提示:_id的前8位字符轉(zhuǎn)換為十進(jìn)制就是時(shí)間戳。例如“5b2f2e24e0f42944105c81d2”,前8位字符“5b2f2e24”轉(zhuǎn)換為十進(jìn)制就是時(shí)間戳“1529818660”,對(duì)應(yīng)的北京時(shí)間是“2018-06-2413:37:40”

4.2 查詢數(shù)據(jù)

對(duì)數(shù)據(jù)集example_data_1進(jìn)行如下查詢:

(1)查詢所有數(shù)據(jù)

(2)查詢特定數(shù)據(jù):查詢“age”為25歲的員工

(3)查詢特定數(shù)據(jù):查詢“age”不小于25的所有記錄

(4)限定返回的數(shù)據(jù)字段類型

在Robo 3T中雙擊集合名字,實(shí)際上是自動(dòng)執(zhí)行了以下這條查詢語(yǔ)句:

db.getCollection(‘example_data_1’).find({})

下面先來(lái)了解一下查詢結(jié)果的三種顯示模式

1.三種顯示模式

Robo 3T顯示出來(lái)的查詢結(jié)果如圖所示,注意右上角方框框住的三個(gè)圖標(biāo)。

圖片

image.png

Robo 3T對(duì)于返回的數(shù)據(jù)有三種組織方式,從左到右分別是:“樹(shù)形模式(Tree Mode)”“表格模式(Table Mode)和“文本模式(TextMode)”。

提示:這三種顯示模式是Robo 3T提供的,不是MongoDB的功能。

2.查詢固定值數(shù)據(jù)

  • (1)查詢所有數(shù)據(jù)。如要查詢所有數(shù)據(jù)值,則直接使用下面兩種寫(xiě)法的任意一種即可:

    db.getCollection(‘example_data_1’).find()

db.getCollection(‘example_data_1’).find({})

  • (2)查詢特定數(shù)據(jù)。如要查詢某個(gè)或者某些具體字段,則可以使用下面的語(yǔ)法來(lái)查詢。如果有多個(gè)字段,則這些字段需要同時(shí)滿足。

例如,對(duì)于數(shù)據(jù)集 example_data_1,要查詢所有“age”字段為25的記錄。則查詢語(yǔ)句可以寫(xiě)為:```

db.getCollection('example_data_1').find({'age': 23})

查詢結(jié)果如圖所示:

圖片

image.png

由于“age”為25的記錄有兩條,于是需要進(jìn)一步縮小查詢范圍——再增加一個(gè)限制條件:

db.getCollection('example_data_1').find({'age': 23,'name':'王小六'})

運(yùn)行結(jié)果如圖所示:

圖片

image.png

總結(jié)一下,“find”的參數(shù)相當(dāng)于一個(gè)字典。字典的 Key 就是字段名,字典的值就是要查詢的值。如果字典有多個(gè)Key,則這些字段需同時(shí)滿足。

3.查詢范圍值數(shù)據(jù)

如要查詢的字段值能夠比較大小,則查詢時(shí)可以限定值的范圍,例如,對(duì)數(shù)據(jù)集example_data_1,要查詢所有“age”字段不小于25的記錄,則需要使用大于等于操作符“$gte”。查詢語(yǔ)句如下:

db.getCollection('example_data_1').find({'age': {'$gte': 23}})





運(yùn)行效果如圖所示:

圖片

image.png

查詢某個(gè)范圍的數(shù)據(jù)會(huì)用到的操作符見(jiàn)下表:

操作符含義
$gt大于
$gte大于等于
$lt小于
$lte小于等于
$ne不等于

使用范圍操作符的查詢語(yǔ)句格式如下:

db.getCollection('example_data_1').find({'age': {'操作符1': 邊界1,'操作符2': 邊界2}})

可以看出,在使用范圍操作符后,原本填寫(xiě)被查詢值的地方現(xiàn)在又變成了一個(gè)字典。這個(gè)字典的Key是各個(gè)范圍操作符,而它們的值是各個(gè)范圍的邊界值。

【舉例1】查詢所有“age”大于21并小于等于24的數(shù)據(jù),查詢語(yǔ)句如下:

db.getCollection('example_data_1').find({'age': {'$lt': 24, '$gt': 21}})

【舉例2】查詢所有“age”大于21并小于等于24的數(shù)據(jù),且“name”不為“夏侯小七”的記錄

db.getCollection('example_data_1').find({
            'age': {
                    '$lt': 24,
              '$gt': 21
              },
            'name':{'$ne':'歐陽(yáng)小七'}
})

4.限定返回哪些字段

“find”命令可以接收兩個(gè)參數(shù):第1個(gè)參數(shù)用于過(guò)濾不同的記錄,第2個(gè)參數(shù)用于修改返回的字段,如果省略第2個(gè)參數(shù),則MongoDB會(huì)返回所有的字段。如要限定字段,則查詢語(yǔ)句的格式如下:

db.getCollection('example_data_1').find(用于過(guò)濾記錄的字典,用于限定字段的字典)

其中,用于限定字段的字典的Key為各個(gè)字段名。其值只有兩個(gè)——0或1。

● 如果值為0,則表示在全部字段中剔除值為0的這些字段并返回。

● 如果值為1,則表示只返回值為1的這些字段。

例如,查詢數(shù)據(jù)集example_data_1,但不返回“address”和“age”字段,查詢語(yǔ)句如下:

db.getCollection('example_data_1').find({}, {'address': 0, 'age': 0})

運(yùn)行結(jié)果為如圖所示:

圖片

image.png

再例如,要求只返回name字段和age字段,則查詢語(yǔ)句如下:

db.getCollection('example_data_1').find({}, {'name': 1, 'age': 1})

運(yùn)行效果如所示:

圖片

image.png

可能已經(jīng)發(fā)現(xiàn),不論是選擇“只返回某些字段”還是“不返回某些字段”,結(jié)果里始終有“_id”。這是因?yàn)椋癬id”比較特殊,它是默認(rèn)要返回的,除非明確說(shuō)明不需要它。即,如果不想要“_id”,則必須在限定字段的字典中把“_id”字段的值設(shè)為0,如圖所示:

圖片

image.png

如果不考慮“_id”,則限定字段的字典里面的值只可能全都是0或全都是1,不可能1和0混用,一旦混用則MongoDB就會(huì)報(bào)錯(cuò)。這從邏輯上很好理解:

(1)如果只要A、B、C,則沒(méi)有提到的自然都是不需要的

(2)如果除A、B、C外其他的全都要,則沒(méi)有提到的自然全都是需要的

提示:只有“_id”很特別,不論其他字段的值是0還是1,如果不需要返回“_id”,則需要把它的值設(shè)為0

5.修飾返回結(jié)果

  • (1)滿足要求的數(shù)據(jù)有多少條——count()命令

如果想知道滿足要求的數(shù)據(jù)有多少條,則可以使用“count()”命令。例如,要查詢所有“age”字段大于21的記錄有多少條,則查詢語(yǔ)句如下:

db.getCollection('example_data_1').find({'age': {'$gt': 21}}).count()

運(yùn)行結(jié)果如圖所示。返回?cái)?shù)字“3”表示有3條記錄滿足要求

圖片

image.png

  • (2)限定返回結(jié)果——“l(fā)imit()”命令

如果查詢的結(jié)果非常多,則可能需要限定返回結(jié)果。此時(shí)就需要使用“l(fā)imit()”命令。它的用法如下:

db.getCollection('example_data_1').find().limit(限制返回的條數(shù))

● 如果限制返回的條數(shù)為一個(gè)數(shù)字,則表示最多返回這么多條記錄。如果超過(guò)限定條數(shù),則只返回限定的條數(shù)

● 如果不足限定的條數(shù),則有多少就返回多少。例如,對(duì)于數(shù)據(jù)集example_data_1,限制只返回4條數(shù)據(jù)。具體命令如下:

db.getCollection('example_data_1').find().limit(4)

運(yùn)行效果如圖所示:

圖片

image.png

  • (3)對(duì)查詢結(jié)果進(jìn)行排序——“sort()”命令

有時(shí)也需要對(duì)查詢結(jié)果進(jìn)行排序,此時(shí)需要使用“sort()”命令。使用方法如下:

db.getCollection('example_data_1').find({'age': {'$gt':21}}).sort({'字段名': -1或者1})

其中,字段的值為-1表示倒序,為1表示正序。例如,對(duì)所有“age”大于21的數(shù)據(jù),按“age”進(jìn)行倒序排列。查詢語(yǔ)句如下:

db.getCollection('example_data_1').find({'age': {'$gt':21}}).sort({'age': -1})

運(yùn)行如下:

圖片

image.png

4.3 修改數(shù)據(jù)

實(shí)例描述數(shù)據(jù)集 example_data_1,“name”為“王小六”的這個(gè)記錄是沒(méi)有“address”字段的?,F(xiàn)在需要為它增加這個(gè)字段,同時(shí)把“work”從“運(yùn)維工程師”改為“DBA”。

(1)更新集合中的單條數(shù)據(jù)。

(2)批量更新同一個(gè)集合中的多條數(shù)據(jù)。

修改操作也就是更新(Update)操作,對(duì)應(yīng)的 MongoDB 命令為“updateOne()”和“updateMany()”。

這兩個(gè)命令只有以下區(qū)別,它們的參數(shù)完全一致。

● updateOne:只更新第1條滿足要求的數(shù)據(jù)

● updateMany:更新所有滿足要求的數(shù)據(jù)

下面以“updateMany”為例來(lái)介紹更新記錄的操作。

1.更新操作的語(yǔ)法

db.getCollection('example_data_1').updateMany(
   參數(shù)1:查詢語(yǔ)句的第一個(gè)字典,
   {'set':{'字段1':'新的值1','字段2','新的值2'}}
)

updateMany的第1個(gè)參數(shù)和“find”的第1個(gè)參數(shù)完全一樣,也是一個(gè)字典,用來(lái)尋找所有需要被更新的記錄。第2個(gè)參數(shù)是一個(gè)字典,它的Key為“$set”,它的值為另一個(gè)字典。這個(gè)字典里面是需要被修改的字段名和新的值。

舉例:

修改“name”為“王小六”的文檔,添加“address”字段,并“work”從“運(yùn)維工程師”改為“DBA”

db.getCollection('example_data_1').updateMany(
   {'name':'王小六'},
   {'$set':{'address':'蘇州','work':'DBA'}}
)

圖片

image.png

再次查看數(shù)據(jù)集,發(fā)現(xiàn)“王小六”的信息已經(jīng)發(fā)生了變化,如圖所示:

圖片

image.png

4.4 刪除數(shù)據(jù)

例如,要從數(shù)據(jù)集example_data_1中刪除字段“hello”值為“world”的這一條記錄。

(1)從集合中刪除單條數(shù)據(jù)

(2)從集合中批量刪除多條數(shù)據(jù)

只要會(huì)查詢數(shù)據(jù),就會(huì)刪除數(shù)據(jù)。為了防止誤刪數(shù)據(jù),一般的做法是先查詢要?jiǎng)h除的數(shù)據(jù),然后再將查出的數(shù)據(jù)刪除

  • (1)查詢字段“hello”中值為“world”的這一條記錄

具體如下:

db.getCollection('example_data_1').find({'hello': 'world'})

db.getCollection(‘example_data_1’).find({‘hello’: ‘world’})

運(yùn)行效果如圖所示:

圖片

image.png

  • (2)把查詢語(yǔ)句的“find”修改為“deleteOne”(如果只刪除第1條滿足要求的數(shù)據(jù)),或把查詢語(yǔ)句的“find”修改為“deleteMany”(如果要?jiǎng)h除所有滿足要求的數(shù)據(jù))

具體命令如下:

db.getCollection('example_data_1').deleteMany({'hello': 'world'})
  • (3)在返回的數(shù)據(jù)中,“acknowledged”為“true”表示刪除成功,“deletedCount”表示一共刪除了1條數(shù)據(jù)

  • (4)再次查詢example_data_1,發(fā)現(xiàn)已經(jīng)找不到被刪除的數(shù)據(jù)了

提示:慎用刪除功能。一般工程上會(huì)使用“假刪除”,即:在文檔里面增加一個(gè)字段“deleted”,如果值為0則表示沒(méi)有刪除,如果值為1則表示已經(jīng)被刪除了。默認(rèn)情況下,deleted字段的值都是0,如需要執(zhí)行刪除操作,則把這個(gè)字段的值更新為1。而查詢數(shù)據(jù)時(shí),只查詢deleted為0的數(shù)據(jù)。這樣就實(shí)現(xiàn)了和刪除一樣的效果,即使誤操作了也可以輕易恢復(fù)

4.5 數(shù)據(jù)去重

在數(shù)據(jù)集example_data_1中,進(jìn)行以下兩個(gè)去重操作。

(1)對(duì)“age”字段去重

(2)查詢所有“age”大于等于24的數(shù)據(jù),再對(duì)“age”進(jìn)行去重。去重操作用到的命令為“distinct()”

格式如下:

db.getCollection('example_data_1').distinct('字段名', 查詢語(yǔ)句的第一個(gè)字典)

distinct()可以接收兩個(gè)參數(shù):

  • 第1個(gè)參數(shù)為字段名,表示對(duì)哪一個(gè)字段進(jìn)行去重。

  • 第2個(gè)參數(shù)就是查詢命令“find()”的第1個(gè)參數(shù)。distinct命令的第2個(gè)參數(shù)可以省略

1.對(duì)“age”字段去重對(duì)“age”字段去重的語(yǔ)句如下:

db.getCollection('example_data_1').distinct('age')

運(yùn)行效果如圖所示:

圖片

image.png

在MongoDB中返回的數(shù)據(jù)是一個(gè)數(shù)組,里面是去重以后的值。

2.對(duì)滿足特定條件的數(shù)據(jù)去重首先查詢所有“age”大于等于20的數(shù)據(jù),然后對(duì)“age”進(jìn)行去重。

db.getCollection('example_data_1').distinct(
   'age',
   {'age':{'$gte':20}}
)

運(yùn)行結(jié)果:

圖片

image.png

提示:能否去重以后再帶上其他字段呢?答案是,用“distinct()”命令不能實(shí)現(xiàn)。要實(shí)現(xiàn)這個(gè)功能,后面介紹

后面會(huì)更新如何使用Python操作MongoDB,請(qǐng)持續(xù)關(guān)注

公眾號(hào):運(yùn)維開(kāi)發(fā)故事

github:https://github.com/orgs/sunsharing-note/dashboard


作者:double冬 運(yùn)維開(kāi)發(fā)故事


歡迎關(guān)注:運(yùn)維開(kāi)發(fā)故事