mongodb tutorial
安装
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/
主要议程
https://docs.mongodb.com/getting-started/python/
- Introduction to MongoDB as well as instructions to Import Example Dataset;
- A brief overview of the Python Driver (PyMongo);
- Basic Insert, Find, Update, Remove operations plus Aggregation;
- Instructions on creating Indexes to improve query performance.
数据库驱动
https://docs.mongodb.com/getting-started/python/client/
安装驱动
使用案例
连接
1 2 3 4 5 6 7
| import pymongo from pymongo import MongoClient from datetime import datetime client = MongoClient("mongodb://127.0.0.1:27017") db = client['test'] coll = db['restaurants']
|
插入
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
| result = db.restaurants.insert_one( { "address": { "street": "2 Avenue", "zipcode": "10075", "building": "1480", "coord": [-73.9557413, 40.7720266] }, "borough": "Manhattan", "cuisine": "Italian", "grades": [ { "date": datetime.strptime("2014-10-01", "%Y-%m-%d"), "grade": "A", "score": 11 }, { "date": datetime.strptime("2014-01-16", "%Y-%m-%d"), "grade": "B", "score": 17 } ], "name": "Vella", "restaurant_id": "41704620" } ) result.inserted_id
|
查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| cursor = db.restaurants.find() cursor = db.restaurants.find({"borough": "Manhattan"}) cursor = db.restaurants.find({"address.zipcode": "10075"}) cursor = db.restaurants.find({"grades.grade": "B"}) cursor = db.restaurants.find({"grades.score": {"$gt": 30}}) cursor = db.restaurants.find({"grades.score": {"$lt": 10}}) cursor = db.restaurants.find({"cuisine": "Italian", "address.zipcode": "10075"}) cursor = db.restaurants.find( {"$or": [{"cuisine": "Italian"}, {"address.zipcode": "10075"}]})
|
排序
1 2 3 4 5 6 7 8 9 10
| # Sort cursor = db.restaurants.find().sort([ ("borough", pymongo.ASCENDING), ("address.zipcode", pymongo.ASCENDING) ]) for index,document in enumerate(cursor): if index > 2: break print(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
| result = db.restaurants.update_one( {"name": "Juni"}, { "$set": { "cuisine": "American (New)" }, "$currentDate": {"lastModified": True} } ) result = db.restaurants.update_one( {"restaurant_id": "41156888"}, {"$set": {"address.street": "East 31st Street"}} ) result = db.restaurants.update_many( {"address.zipcode": "10016", "cuisine": "Other"}, { "$set": {"cuisine": "Category To Be Determined"}, "$currentDate": {"lastModified": True} } ) result.matched_count result.modified_count
|
删除
1 2 3 4 5 6 7 8 9 10 11
| result = db.restaurants.delete_many({"borough": "Manhattan"}) result.deleted_count result = db.restaurants.delete_many({}) db.restaurants.drop()
|
聚集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| cursor = db.restaurants.aggregate( [ {"$group": {"_id": "$borough", "count": {"$sum": 1}}} ] ) for document in cursor: print(document) cursor = db.restaurants.aggregate( [ {"$match": {"borough": "Queens", "cuisine": "Brazilian"}}, {"$group": {"_id": "$address.zipcode", "count": {"$sum": 1}}} ] ) for document in cursor: print(document)
|
mongodb shell 用法
https://docs.mongodb.com/manual/mongo/
启动 mongodb shell
系统全局信息
1 2 3 4 5 6 7 8 9 10 11
| # 显示当前使用的数据库名称 db.getName() # 当前数据库版本 db.version() # 查看当前数据库的链接机器地址 db.getMongo() # 显示当前数据库状态,包含数据库名称,集合个数,当前数据库大小 db.stats()
|
db
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| # 当前使用的db db # 有哪些db show dbs db.getSiblingDB() # 新建/切换db use myNewDatabase # 删除当前使用的数据库 db.dropDatabase() # 修复当前数据库 db.repairDatabase() # 查看数据库中有那些个集合 db.getCollectionNames()
|
collection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| db.myCollection.insert( { x: 1 } ); show collections db["3test"].insert({ b:2 }) db["3test"].find() db.getCollection("3test").find() db.collection.remove() db.collection.drop() db.3test.find({"exclude":false}).count() db.sv_lsh.find({"exclude":false})[0]["value"][0].length
|
复杂查询
db.fv_20170210.find({“value”:1929})
PersonModel.find({ favouriteFoods: { “$in” : [“sushi”]} }, …);
db.runCommand({“distinct”: feature_vector_collection_name, “key”: “app_index”})
db.runCommand({“distinct”: db.fv_20170210.find({“value”:1929}),”key”:”app_index”})
var lst = db.fv_20170210.find({“value”:9235});
while(lst.hasNext()) db.test.insert(lst.next());
db.runCommand({“distinct”: “test”, “key”:”app_index”})
db.test.drop()
db.runCommand({“distinct”: “test”, “key”:”app_index”})[“values”].length
聚合
聚合 平均值,求和
http://www.runoob.com/mongodb/mongodb-aggregate.html
1 2 3 4 5
| var lst = db.fv_20170210.find(); while(lst.hasNext()) { var doc = lst.next(); printjson(doc); }
|
1 2 3 4 5
| var lst = db.fv_20170210.find(); while(lst.hasNext()) { var doc = lst.next(); db.app_info.insert({"app_index":doc["app_index"],"number":doc["value"].length, "item":"abc"}); }
|
1 2 3 4 5 6 7 8 9 10 11
| db.app_info.aggregate( [ { $group: { _id: "$item", avgNumber: { $avg: "$number" } } } ] )
|
https://docs.mongodb.com/manual/reference/operator/aggregation/avg/
输出
1 2 3 4 5 6
| db.myCollection.find().pretty() print() to print without formatting print(tojson(<obj>)) to print with JSON formatting and equivalent to printjson() printjson() to print with JSON formatting and equivalent to print(tojson(<obj>))
|
其他
up/down 历史命令
tab 可以autocomplete, 单击或连击两下。
exit 退出
基本概念
MongoDB The Definitive Guide
BSON
在MongoDB中,文档是对数据的抽象,它被使用在Client端和Server端的交互中。所有的Client端(各种语言的Driver)都会使用这种抽象,它的表现形式就是我们常说的BSON(Binary JSON )。
BSON是一个轻量级的二进制数据格式。MongoDB能够使用BSON,并将BSON作为数据的存储存放在磁盘中。
当Client端要将写入文档,使用查询等等操作时,需要将文档编码为BSON格式,然后再发送给Server端。同样,Server端的返回结果也是编码为BSON格式再放回给Client端的。
使用BSON格式出于以下3种目的:
效率
BSON是为效率而设计的,它只需要使用很少的空间。即使在最坏的情况下,BSON格式也比JSON格式再最好的情况下存储效率高。
传输性
在某些情况下,BSON会牺牲额外的空间让数据的传输更加方便。比如,字符串的传输的前缀会标识字符串的长度,而不是在字符串的末尾打上结束的标记。这样的传输形式有利于MongoDB修改传输的数据。
性能
最后,BSON格式的编码和解码都是非常快速的。它使用了C风格的数据表现形式,这样在各种语言中都可以高效地使用。
更多关于BSON的介绍,可以参考:http://www.bsonspec.org。
写入协议
Client端访问Server端使用了轻量级的TCP/IP写入协议。这种协议在MongoDB Wiki中有详细介绍,它其实是在BSON数据上面做了一层简单的包装。比如说,写入数据的命令中包含了1个20字节的消息头(由消息的长度和写入命令标识组成),需要写入的Collection名称和需要写入的数据。
数据文件
在MongoDB的数据文件夹中(默认路径是/data/db)由构成数据库的所有文件。每一个数据库都包含一个.ns文件和一些数据文件,其中数据文件会随着数据量的增加而变多。所以如果有一个数据库名字叫做foo,那么构成foo这个数据库的文件就会由foo.ns,foo.0,foo.1,foo.2等等组成。
数据文件每新增一次,大小都会是上一个数据文件的2倍,每个数据文件最大2G。这样的设计有利于防止数据量较小的数据库浪费过多的空间,同时又能保证数据量较大的数据库有相应的空间使用。
MongoDB会使用预分配方式来保证写入性能的稳定(这种方式可以使用–noprealloc关闭)。预分配在后台进行,并且每个预分配的文件都用0进行填充。这会让MongoDB始终保持额外的空间和空余的数据文件,从而避免了数据增长过快而带来的分配磁盘空间引起的阻塞。
名字空间和盘区
每一个数据库都由多个名字空间组成,每一个名字空间存储了相应类型的数据。数据库中的每一个Collection都有各自对应的名字空间,索引文件同样也有名字空间。所有名字空间的元数据都存储在.ns文件中。
名字空间中的数据在磁盘中分为多个区间,这个叫做盘区。在下图中,foo这个数据库包含3个数据文件,第三个数据文件属于空的预分配文件。头两个数据文件被分为了相应的盘区对应不同的名字空间。
上图显示了名字空间和盘区的相关特点。每一个名字空间可以包含多个不同的盘区,这些盘区并不是连续的。与数据文件的增长相同,每一个名字空间对应的盘区大小的也是随着分配的次数不断增长的。这样做的目的是为了平衡名字空间浪费的空间与保持某一个名字空间中数据的连续性。上图中还有一个需要注意的名字空间:$freelist,这个名字空间用于记录不再使用的盘区(被删除的Collection或索引)。每当名字空间需要分配新的盘区的时候,都会先查看$freelist是否有大小合适的盘区可以使用。
内存映射存储引擎
MongoDB目前支持的存储引擎为内存映射引擎。当MongoDB启动的时候,会将所有的数据文件映射到内存中,然后操作系统会托管所有的磁盘操作。这种存储引擎有以下几种特点:
http://blog.csdn.net/yiqijinbu/article/details/9053467
http://www.tuicool.com/articles/iARr2m