mongodb

  1. download:https://www.mongodb.com/try/download/enterprise

  2. install

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 将解压以后的文件夹放在/usr/local
    sudo mv mongodb-osx-x86_64-4.0.9/ /usr/local/
    sudo ln -s mongodb-macos-x86_64-4.4.4 mongodb

    # ENV PATH
    export PATH=/usr/local/mongodb/bin:$PATH

    # 创建日志及数据存放的目录
    sudo mkdir -p /usr/local/var/mongodb
    sudo mkdir -p /usr/local/var/log/mongodb
    sudo chown [amber] /usr/local/var/mongodb
    sudo chown [amber] /usr/local/var/log/mongodb
  3. configuration

    1
    2
    3
    4
    5
    6
    7
    8
    # 后台启动
    mongod --dbpath /usr/local/var/mongodb --logpath /usr/local/var/log/mongodb/mongo.log --fork

    # 控制台启动
    mongod --config /usr/local/etc/mongod.conf

    # 查看状态
    ps aux | grep -v grep | grep mongod
  4. run

    1
    2
    3
    # 在db环境下启动一个终端
    cd /usr/local/mongodb/bin
    ./mongo
  5. original settings

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 显示所有数据的列表
    > show dbs
    admin 0.000GB
    config 0.000GB
    local 0.000GB
    # 三个系统保留的特殊数据库

    # 连接/创建一个指定的数据库
    > use local
    switched to db local

    # 显示当前数据库, 如果没use默认为test
    > db
    test

    # 【!!重要】关闭服务
    之前服务器被kill -9强制关闭,数据库丢失了
    > use admin
    switched to db admin
    > db.shutdownServer()
    server should be down...
  6. concepts

  7. 文档document

    一组key-value对,如上面左图中的一行记录,如上面右图中的一个dict

  8. 集合collection

    一张表,如上面左图和上面右图

  9. 主键primary key

    唯一主键,ObjectId类型,自定生成,有标准格式

  10. 常用命令

    10.1 创建/删除/重命名db

    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
    # 切换至数据库test1
    > use test1

    # 插入一条doc, db.COLLECTION_NAME.insert(document)
    # db要包含至少一条文档,才能在show dbs的时候显示(才真正创建)
    > db.sheet1.insert({'name': img0})

    # 显示当前已有数据库
    > show dbs

    # 删除指定数据库
    > use test1
    > db.dropDatabase()

    # 旧版本(before4.0)重命名:先拷贝一份,在删除旧的
    > db.copyDatabase('OLDNAME', 'NEWNAME');
    > use old_name
    > db.dropDatabase()
    # 新版本重命名:dump&restore,这个东西在mongodb tools里面,要另外下载,可执行文件放在bin下
    # mongodump # 将所有数据库导出到bin/dump/以每个db名字命名的文件夹下
    # mongodump -h dbhost -d dbname -o dbdirectory
    # -h: 服务器地址:端口号
    # -d: 需要备份的数据库
    # -o: 存放位置(需要已存在)
    mongodump -d test -o tmp/
    # 在恢复备份数据库的时候换个名字:mongorestore -h dbhost -d dbname path
    mongorestore -d test_bkp tmp/test
    # 这时候可以看到一个新增了一个叫test_bkp的db

    10.2 创建/删除/重命名collection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 创建:db.createCollection(name, options)
    > db.createCollection('case2img')

    # 显示已有tables
    > show collections

    # 不用显示创建,在db insert的时候会自动创建集合
    > db.sheet2.insert({"name" : "img2"})

    # 删除:db.COLLECTION_NAME.drop()
    > db.sheet2.drop()

    # 重命名:db.COLLECTION_NAME.renameCollection('NEWNAME')
    > db.sheet2.renameCollection('sheet3')
    # 复制:db.COLLECTION_NAME.aggregate({$out: 'NEWNAME'})
    > db.sheet2.aggregate({ $out : "sheet3" })

    10.3 插入/显示/更新/删除document

    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    # 插入
    db.COLLECTION_NAME.insert(document)
    db.COLLECTION_NAME.save(document)
    db.COLLECTION_NAME.insertOne()
    db.COLLECTION_NAME.insertMany()

    # 显示已有doc
    db.COLLECTION_NAME.find()

    # 更新doc的部分内容
    db.COLLECTION_NAME.update(
    <query>, # 查询条件
    <update>, # 更新操作
    {
    upsert: <boolean>, # if true 如果不存在则插入
    multi: <boolean>, # find fist/all match
    writeConcern: <document>
    }
    )
    > db.case2img.insert({"case": "s0", "name": "img0"})
    > db.case2img.insert({"case": "s1", "name": "img1"})
    > db.case2img.find()
    > db.case2img.update({'case': 's1'}, {$set: {'case': 's2', 'name': 'img2'}})
    > db.case2img.find()

    # 给doc的某个key重命名
    db.COLLECTION_NAME.updateMany(
    {},
    {'$rename': {"old_key": "new_key"}}
    )

    # 更新整条文档by object_id
    db.COLLECTION_NAME.save(
    <document>,
    {
    writeConcern: <document>
    }
    )
    > db.case2img.save({"_id": ObjectId("60474e4b77e21bad9bd4655a"), "case":"s3", "name":"img3"})

    # 删除满足条件的doc
    db.COLLECTION_NAME.remove(
    <query>,
    {
    justOne: <boolean>, # find fist/all match
    writeConcern: <document>
    }
    )
    > db.case2img.remove({"case": "s0"})

    # 删除所有doc
    > db.case2img.remove({})

    10.4 简单查询find

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    > db.case2img.insert({"case": "s0", "name": "img0"})
    > db.case2img.insert({"case": "s1", "name": "img1"})
    > db.case2img.insert({"case": "s2", "name": "img2"})
    > db.case2img.insert({"case": "s2", "name": "img3"})

    # 查询表中的doc:db.COLLECTION_NAME.find({query})
    > db.case2img.find({'case': s2})
    > db.case2img.find({'case': 's1'}, {"name":1}) # projection的value在对应的key-value是list的时候有意义

    # 格式化显示查询结果:db.COLLECTION_NAME.find({query}).pretty()
    > db.case2img.find({'case': s2}).pretty()

    # 读取指定数量的数据记录:db.COLLECTION_NAME.find({query}).limit(NUMBER)
    > db.case2img.find({'case': {$type: 'string'}}).limit(1)

    # 跳过指定数量的数据:db.COLLECTION_NAME.find({query}).skip(NUMBER)
    > db.case2img.find({'case': {$type: 'string'}}).skip(1)

    10.5 条件操作符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    (>) 大于 - $gt
    (<) 小于 - $lt
    (>=) 大于等于 - $gte
    (<=) 小于等于 - $lte
    (or) 或 - $or

    > db.case2img.update({'case':'s1'}, {$set: {"name":'img1', 'size':100}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.case2img.update({'case':'s2'}, {$set: {"name":'img2', 'size':200}})

    # 查询size>150的doc
    > db.case2img.find({'size': {$gt: 150}})

    # 查询满足任意一个条件的doc
    > db.case2img.find({'$or': [{'case':'s1'}, {'size': {$gt: 150}}]})

    10.6 数据类型操作符

    1
    2
    3
    4
    5
    type(KEY)等于 - $type

    # 比较对象可以是字符串/对应的reflect NUM
    > db.case2img.find({'case': {$type: 'string'}})
    > db.case2img.find({'case': {$type: '0'}})

    10.7 排序find().sort

    1
    2
    3
    4
    # 通过指定字段&指定升序/降序来对数据排序:db.COLLECTION_NAME.find().sort({KEY:1/-1})
    > db.case2img.find().sort({'name':1})

    # skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的 limit()。

    10.8 索引

    skip

    10.9 聚合aggregate

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 用于统计 db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

    # by group
    > db.case2img.aggregate([{$group: {_id: '$case', img_num:{$sum:1}}}])
    group by key value 'case'
    count number of items in each group
    refer to the number as img_num

    > db.case2img.aggregate([{$group: {_id: '$case', img_num:{$sum:'$size'}}}])
    计算每一个group内,size值的总和

    # by match
    > db.case2img.aggregate([{$match: {'size': {$gt:150}}},
    {$group:{_id: null, totalsize: {$sum: '$size'}}}])
    类似shell的管道,match用来筛选条件,符合条件的送入下一步统计

    > db.case2img.aggregate([{$skip: 4},
    {$group:{_id: null, totalsize: {$sum: '$size'}}}])
  11. 快速统计distinct

    1
    2
    db.case2img.distinct(TAG_NAME)
    # 注意如果distinct的内容太长,超过16M,会报distinct too big的error,推荐用聚合来做统计
1
2
3
4
5
6
7
8
9
10
11
12
	
12. pymongo

用python代码来操作数据库

先安装:pip install pymongo

11.1 连接client

```python
from pymongo import MongoClient
Client = MongoClient()

11.2 获取数据库

1
2
db = Client.DB_NAME
db = Client['DB_NAME']

11.3 获取collection

1
2
collection = db.COLLECTION_NAME
collection = db['COLLECTION_NAME']

11.4 插入doc

1
2
3
4
5
6
7
8
9
10
11
12
# insert one
document1 = {'x':1}
document2 = {'x':2}
post_1 = collection.insert_one(document1).inserted_id
post_2 = collection.insert_one(document2).inserted_id
print(post_1)

# insert many
new_document = [{'x':1},{'x':2}]
# new_document = [document1,document2] 注意doc是神拷贝,只能作为一条doc被插入一次
result = collection.insert_many(new_document).inserted_ids
print(result)

11.5 查找

1
2
3
4
5
6
7
8
9
10
from bson.objectid import ObjectId

# find one 返回一条doc
result = collection.find_one()
result = collection.find_one({'case': 's0'})
result = collection.find_one({'_id': ObjectId('604752f277e21bad9bd46560')})

# find 返回一个迭代器
for _, item in enumerate(collection.find()):
print(item)

11.6 更新

1
2
3
4
5
6
# update one
collection.update_one({'case':'s1'},{'$set':{'size':300}})
collection.update_one({'case':'s1'},{'$push':{'add':1}}) # 追加数组内容

# update many
collection.update_many({'case':'s1'},{'$set':{'size':300}})

11.7 删除

1
2
3
# 在mongo shell里面是remove方法,在pymongo里面被deprecated成delete方法
collection.delete_one({"case": "s2"})
collection.delete_many({"case": "s1"})

11.8 统计

1
2
3
4
5
# 计数:count方法已经被重构
print(collection.count_documents({'case':'s0'}))

# unique:distinct方法
print(collection.distinct('case'))

​ 11.9 正则

​ mongo shell命令行里的正则和pymongo脚本里的正则写法是不一样的,因为python里面有封装正则方法,然后通过bson将python的正则转换成数据库的正则

1
2
3
4
5
6
7
8
9
10
# pymongo
import re
import bson

pattern = re.compile(r'(.*)-0[345]-(.*)')
regex = bson.regex.Regex.from_native(pattern)
result = collection.aggregate([{'$match': {'date': regex}}])

# mongo shell
> db.collection.find({date:{$regex:"(.*)-0[345]-(.*)"}})