MongoDB概览

简介

MongoDB是首先是一种NoSQL(not only SQL)数据库,即非关系数据库。NoSQL有很多种,我们介绍的MongoDB属于文档数据库。 与传统的MySQL,Oracle等关系数据库比,MongoDB在分布式的大规模数据存储上有一定优势。本文介绍了MongoDB的一些基本用法,并在最后介绍其python的接口。

使用

Windows下,在官网下载安装包后,可直接安装。
安装完成后我们开始建立一个简单的数据库。我们新建一个文件夹MyDB,在此文件夹下建立3个子文件夹conf, data, log
在conf文件夹下,我们新建数据库的配置文件mongo.ini,指定数据库的端口,存放数据的路径以及日志的路径。(简单起见,本文暂不介绍数据库权限)

port = 11111
dbpath = E:\MongoDB\MyDB\data
logpath = E:\MongoDB\MyDB\log\mongo.log

然后我们使用命令mongod -f mongo.ini启动服务器。(注意环境变量的配置)

服务器启动之后可以在相应的data文件夹和log文件夹中看到生成的数据文件和日志文件。

之后使用命令mongo 127.0.0.1:11111可连接到数据库。这里由于没有启用权限控制,因此有一些Warning.

MongoDB shell version v3.4.3
connecting to: 127.0.0.1:11111
MongoDB server version: 3.4.3
Server has startup warnings:
2017-04-19T12:23:19.801+0800 I CONTROL  [initandlisten]
2017-04-19T12:23:19.801+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2017-04-19T12:23:19.801+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2017-04-19T12:23:19.801+0800 I CONTROL  [initandlisten]
>

基本操作

使用命令show dbs查看当前有哪些数据库

> show dbs
admin     0.000GB
local     0.000GB

我们现在想创建一个新的数据库learn,可以使用命令use learn,切换到learn数据库。此时learn数据库尚未建立,当我们插入一条数据后,其会自动建立。

插入

现在我们使用insert指令来插入一个文档。

> db.my_collect.insert({key:"value"})
WriteResult({ "nInserted" : 1 })

这里涉及到了collection的概念。MongoDB中的collection可以类比为关系数据库中的表(table),一个数据库会有若干个colleciton,每个collection又有若干个文档。其与table的不同在于,collection不需要一个预先设定的模式scheme,其中的每个记录可以有完全不同的项。因为collection不用显示地创建,这里我们直接指定了一个暂时不存在的my_collect,并直接向其插入数据。

MongoDB中的文档格式为BSON,一种非常类似JSON的数据格式,我们每次插入的数据,都需要符合这种格式。这篇文档给出了BSON支持的数据类型的一个简要的说明。

BSON


MongoDB的语法也类似于JavaScript,所以也可以这样使用循环来插入数据。

> for (var i = 0; i < 5; i++) db.my_collect.insert({num1:i,num2:5-i})


查询

现在我们来看看得到的结果。

> show collections
my_collect
> db.my_collect.find()
{ "_id" : ObjectId("58f6fe526512d30086571807"), "key" : "value" }
{ "_id" : ObjectId("58f6fe686512d30086571808"), "num1" : 0, "num2" : 5 }
{ "_id" : ObjectId("58f6fe686512d30086571809"), "num1" : 1, "num2" : 4 }
{ "_id" : ObjectId("58f6fe686512d3008657180a"), "num1" : 2, "num2" : 3 }
{ "_id" : ObjectId("58f6fe686512d3008657180b"), "num1" : 3, "num2" : 2 }
{ "_id" : ObjectId("58f6fe686512d3008657180c"), "num1" : 4, "num2" : 1 }

使用show collections查看数据库中的collections,然后使用find指令,查询collection中的数据。find指令可以指定查询的条件,这里我们没有指定则返回所有的数据。

可以注意到,对每个文档,都有一个_id项,这是MongoDB自动生成的ID,可以确保全数据库中唯一。其具体的意义,参见这里。我们也可以手动指定数据的_id,但一般不推荐这么做。每个文档都需要一个_id项作为主键。

我们接着来看如何进行查询。如前所述,使用find指令可以查询数据,现在我们加上查询条件。

> db.my_collect.find({num1:3})
{ "_id" : ObjectId("58f6fe686512d3008657180b"), "num1" : 3, "num2" : 2 }
> db.my_collect.find({num1:{$gt:0}, num2:{$lt:3}})
{ "_id" : ObjectId("58f6fe686512d3008657180b"), "num1" : 3, "num2" : 2 }
{ "_id" : ObjectId("58f6fe686512d3008657180c"), "num1" : 4, "num2" : 1 }

查询的条件需要满足如下的格式

{ <field1>: <value1>, <field2>: <value2>, ... }

观察第二次查询,其查询的是num1比0大,num2比3小的文档。MongoDB使用特殊的运算符$gt,$lt表示大于和小于。

MongoDB的查询条件默认是逻辑与的,也就是当给出的所有条件都满足才会被查到。如果是想使用逻辑或,即所有条件只要满足一条,则需要使用特殊的$or运算符。

> db.my_collect.find({$or:[{num1:{$gt:3}},{key:"value"}]})
{ "_id" : ObjectId("58f6fe526512d30086571807"), "key" : "value" }
{ "_id" : ObjectId("58f6fe686512d3008657180c"), "num1" : 4, "num2" : 1 }


我们再看一个稍复杂的例子。

> db.my_collect.insert({embbed:{num3:300}, num1:[{"value":100}]})
WriteResult({ "nInserted" : 1 })
> db.my_collect.find({"embbed.num3":300})
{ "_id" : ObjectId("58f706526512d3008657180f"), "embbed" : { "num3" : 300 }, "num1" : [ { "value" : 100 } ] }
> db.my_collect.find({"num1.value":100})
{ "_id" : ObjectId("58f706526512d3008657180f"), "embbed" : { "num3" : 300 }, "num1" : [ { "value" : 100 } ] }
>

我们插入了一个文档。

{ 
    "_id" : ObjectId("58f706526512d3008657180f"),
    "embbed" : { "num3" : 300 },
    "num1" : [ { "value" : 100 } ]
}

我们要查找embbed中的num3为300的项,需要使用"embbed.num3":300来指定,这里使用了.运算符,同时必须使用引号括起来。如果想查询的项放在了数组中,情况类似。


更新

MongoDB中,更新的指令是update,还是先来看一个例子

> db.my_collect.find({key:"value"})
{ "_id" : ObjectId("58f6fe526512d30086571807"), "key" : "value" }
> db.my_collect.update({key:"value"}, {num1:80})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.my_collect.find({key:"value"})
> db.my_collect.find({num1:80})
{ "_id" : ObjectId("58f6fe526512d30086571807"), "num1" : 80 }

我们更新了{key:"value"}这个文档,更新之后,_id不变,但是整个文档被替换为了num1:80,原本的key项被覆盖了。

如果我们只是想局部更新而非替换,需使用$set运算符。

> db.my_collect.update({num1:80}, {$set:{num2:97}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.my_collect.find({num1:80})
{ "_id" : ObjectId("58f6fe526512d30086571807"), "num1" : 80, "num2" : 97 }

update指令默认指更新查找到的第一个文档,如果想要更新所有文档,需要额外指定第三个参数为{multi:true}.

> db.my_collect.update({num1:{$lt:4}}, {$set:{num2:0}}, {multi:true})
WriteResult({ "nMatched" : 4, "nUpserted" : 0, "nModified" : 4 })
> db.my_collect.find()
{ "_id" : ObjectId("58f6fe526512d30086571807"), "num1" : 80, "num2" : 97 }
{ "_id" : ObjectId("58f6fe686512d30086571808"), "num1" : 0, "num2" : 0 }
{ "_id" : ObjectId("58f6fe686512d30086571809"), "num1" : 1, "num2" : 0 }
{ "_id" : ObjectId("58f6fe686512d3008657180a"), "num1" : 2, "num2" : 0 }
{ "_id" : ObjectId("58f6fe686512d3008657180b"), "num1" : 3, "num2" : 0 }
{ "_id" : ObjectId("58f6fe686512d3008657180c"), "num1" : 4, "num2" : 1 }
{ "_id" : ObjectId("58f706526512d3008657180f"), "embbed" : { "num3" : 300 }, "num1" : [ { "value" : 100 } ] }
>


删除

MongoDB中的删除指令是remove. 删除所有条件匹配的文档,如果只想删除第一个满足条件的文档,需要额外指定第二个参数{justOne:true}.

> db.my_collect.remove({num2:0}, {justOne:true})
WriteResult({ "nRemoved" : 1 })
> db.my_collect.find({num2:0})
{ "_id" : ObjectId("58f6fe686512d30086571809"), "num1" : 1, "num2" : 0 }
{ "_id" : ObjectId("58f6fe686512d3008657180a"), "num1" : 2, "num2" : 0 }
{ "_id" : ObjectId("58f6fe686512d3008657180b"), "num1" : 3, "num2" : 0 }
> db.my_collect.remove({num2:0})
WriteResult({ "nRemoved" : 3 })
> db.my_collect.find({num2:0})
>

如果想删除整个collection,可以使用drop指令

> db.my_collect.drop()
true
> show collections
>


索引

索引可以加速查询,我们会对经常查找的项建立索引。首先,我们可以使用getIndexes查看已有的索引。

> db.my_collect.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "learn.my_collect"
        }
]

MongoDB会自动给_id项建立索引。我们也可以用指令createIndex方法建立自己的索引。

> db.my_collect.drop()
true
> for (var i = 1; i < 100; i++) db.my_collect.insert({x:i, y:0})
WriteResult({ "nInserted" : 1 })
> db.my_collect.createIndex({x:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.my_collect.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "learn.my_collect"
        },
        {
                "v" : 2,
                "key" : {
                        "x" : 1
                },
                "name" : "x_1",
                "ns" : "learn.my_collect"
        }
]
>


Python接口

使用命令pip install pymongo安装MongoDB的Python驱动。

我们使用下面的代码来说明pymongo的用法。

#-*- coding=utf-8 -*-

from pymongo import MongoClient

client = MongoClient("mongodb://127.0.0.1:11111")  #建立连接
db = client['learn']         #数据库
db['pytest'].drop()
coll = db['pytest'] #collection

# 插入文档,返回结果包括_id
for i in range(100):
    coll.insert_one(
        {
            "x" : i,
            "y" : i%10,
        }
        )

#查找y=9的文档并打印
cursor = coll.find({"$or":[{"x":{"$lt":3}}, {"y":9}]}) # x<3 or y==9
for doc in cursor:
    print(doc)

#更新
coll.update_many({"x":{"$lt":6}}, {"$set":{"z":2}}) # x < 6 ==> z=2
coll.update_one({"x":{"$lt":6}}, {"$set":{"z":1}})  # x < 6 --> z=1

cursor = coll.find({"x":{"$lt":6}}) # x < 6
for doc in cursor:
    print(doc)

#删除
coll.delete_many({"x":{"$gt":5}}) # x > 5
cursor = coll.find()
for doc in cursor:
    print(doc)


See also:

  1. https://docs.mongodb.com/getting-started/shell/
  2. https://docs.mongodb.com/getting-started/python/
NSW UPNP路由器端口映射工具 是一款免费的绿色版路由器TCP端口映射设置软件。 支持UPNP功能的路由器(一般路由器均支持此功能),无需管理帐号和密码,也不需进入路由器管理界面,可以直接通过本软件,进行端口映射设置。 运行软件后,您既可以通过点击“检测本机”按钮自动识别本机内网IP与路 由器IP ,也可以手动填写。点击执行设置即可生效。 注意事项: 1)不支持UPNP或者关闭了UPNP功能的路由器,不能通过本软件设置,需 要登录路由 器管理界面手动设置端口映射。 2)有些路由器在通过UPNP功能设置端口映射后,如果一定时间内没有数 据通讯则自 动回收该端口,您可以通过本软件“定时刷新”功能避免端口被回收。 3)通过UPNP功能设置的端口映射,在路由器重启后将被回收,您需要在 路由器重启 后重新用本软件进行UPNP端口映射设置。 您也可以通过本软件“定时刷新 ”功能避 免端口被回收。 QQ交流群:205946510欢迎加入~ ======================================== ======================= 软件说明及相关协议 ======================================== ======================= 软件产品许可协议:   本软件作者 是本协议中向用户许可﹑租赁或销售的一切知识产权的 所有人,有权向用户许可﹑ 租赁或销售前述知识产权。除本协议具体规 定的以外,未授予用户任何许可,无论明示的或默示的。 使用限制: 1.用户只可在一台机器上使用本系统; 2.只有在以下之一前提下,可将本系统用于多用户环境或网络系统上: *本系统明文许可用于多用户环境或网络系统上; *使用本系统的每一节点及终端都已被授权许可使用。 3.除本协议的条款和条件明确规定的以外,用户不得执行﹑使用﹑复制或 修改本系统; 4.用户不得以反向设计软件或者反向设计软件的任何硬件﹑固体执行为目 的,拆编﹑ 反装﹑分析或以其他方式研究软件。 5.本系统试用共享版本只限于软件学习交流使用,不允许使用于商业应用 目的,商业应用请向我们注册本系统,同时你也必须支付购买本系统所需 的费用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值