前面非root安装MongoDB安装MongoDB后,启动mongod进程后,就可以利用PyMongo连接数据库进行操作。 首先安装PyMongo

pip install pymongo

按照MongoDB的默认配置,本地的IP是localhost,端口是27017

from pymongo import MongoClient
client = MongoClient('localhost',27017)
# or
client = MongoClient('mongodb://localhost:27017')

如果是远程数据库,可以把上面的localhost和端口换成对应的IP和服务器端口。 MongoDB中可以存放多个数据库,可以用下面的方法查看所有的数据库名,连接某个数据库:

client.database_names()
# [u'admin', u'charts', u'flask', u'formtable', u'local', u'test'] 已经创建的database
db = client.test
# or
db = client['test']

一个数据库也可以存在多个collection:

db.collection_names()
# [u'formtable', u'user', u'demo', u'worldbank'] 之前创建的collection
# 连接到worldbank collection
worldbank = db.worldbank

数据存储

MongoDB很有意思,当你要创建一个新的database或collection时,不需预告创建,当你使用时会自动创建。下面展示创建一个posts database,并在里面插入一条记录(document):

posts = db.posts
import datatime
post = {"author": "Mike",
         "text": "My first blog post!",
         "tags": ["mongodb", "python", "pymongo"],
         "date": datetime.datetime.utcnow()}
post_id = posts.insert_one(post).inserted_id
# 查看post_id
post_id
# ObjectId('59e50037a92c965e978e4e84')
db.collection_names(include_system_collections=False)
# [u'formtable', u'posts', u'user', u'demo', u'worldbank'] 多了个posts,过滤了MongoDB系统需要的database

在PyMongo中可以直接插入一个字典,不需要进行任何处理,这对于可以转换成字典结构的json数据非常方便。 上面得到的一个ObjectId是特殊的对象,随着记录的创建而创建,而且在数据库是唯一的。可以用str(post_id)得到一个16进制的字符串。如果按照这个字符串进行排序可以得到记录创建时间的先后顺序。如果想要从字符串转换为ObjectId可以利用bson模块:

from bson import ObjectId
_id = ObjectId('59e50037a92c965e978e4e84')

如果存在多条记录的话,也可以一次性的插入到数据库中:

new_posts = [
              {"author": "Mike",
               "text": "Another post!",
               "tags": ["bulk", "insert"],
               "date": datetime.datetime(2009, 11, 12, 11, 14)},
              {"author": "Eliot",
               "title": "MongoDB is fun",
               "text": "and pretty easy too!",
               "date": datetime.datetime(2009, 11, 10, 10, 45)}
             ]
posts_id = posts.insert_many(new_posts)
posts_id       

插入的时候把多个字典放到一个列表中,使用insert_many()插入,最后返回的posts_id也是一个ObjectId列表。PyMongo中提供的其他数据操作方法都类似insert_oneinsert_many一样,分成单个记录和多个记录。

数据查询

find_one()find()提供了数据查询方法,前者只显示满足条件的第一个记录,而后者返回所有符合条件的记录。如果不提供具体的查询条件,find_one()返回数据库中的第一条记录,find()返回数据库中的所有记录。

posts.find_one()
post.find()
# 两个返回一样的结果,因为posts 数据库中只有一条记录

根据某个field的值进行查询:

one=posts.find_one({'author':'Mike'})
many=posts.find({'author':'Mike'})

上面是按照author field等于Mike进行查询,把查询条件包装成一个字典,field为key,对应的值为value。返回的one是一个字典,而many是一个数据库的指针(cursor),对应数据库中的具体位置,可以利用循环遍历结果:

for x in many:
  print x

遍历后如果还想再遍历一次many时,会发现里面什么也没有。需要重新用find()查询一遍。

数据更新

PyMongo提供了update_oneupdate_many。update可以看成是更新field中的信息,replace是用新的值覆盖这条记录,二者的使用也不一样

posts.update_one({'author':'Mike'}, {'$set':{'author':'HiMike'}})

把数据库中找到的第一个author field等于Mike的修改HiMike,update_many()能把所有的符合条件的进行更新

数据删除

delete_one()delete_many()可以用来删除数据。括号中是具筛选条件:

posts.delete_one({'author':'Mike'})
posts.delete_many({'author':'Mike'})

数据过滤

对于更复杂的过滤条件,MongoDB也提供了许多query operators,看语法好像是perl里面使用的样子。Query and Projection Operators。先认识下常见的比较操作符:

  • $eq Matches values that are equal to a specified value.
  • $gt Matches values that are greater than a specified value.
  • $gte Matches values that are greater than or equal to a specified value.
  • $in Matches any of the values specified in an array.
  • $lt Matches values that are less than a specified value.
  • $lte Matches values that are less than or equal to a specified value.
  • $ne Matches all values that are not equal to a specified value.
  • $nin Matches none of the values specified in an array.

试试$eq操作符:

posts.find_one({"author":{"$eq":"Mike"}})

查找一个author等于Mike的记录。如果有多个查询条件人:

date = datetime.datetime.utcnow()
post = posts.find({"author":{"$eq":"Mike"}, "date":{"$lt":date}})
post.count()

可以按照authordate进行过滤,最后有2个记录符合条件。count()方法要以获得记录的数目。

数据排序

PyMongo提供了sort()方法对查询的数据进行排序。对单列进行排序

from pymongo import ASCENDING, DESCENDING
mongo.db.demo.find().sort('author', ASCENDING)

对多列进行排序

mongo.db.demo.find().sort([('author', ASCENDING),('date',DESCENDING)])

ASCENDINGDESCENDING的值分别是1和-1。

建立索引

为数据库添加索引可以更快地进行搜索,同时也会添加一些额外的功能。为posts中的author添加一个unique index:

db.posts.create_index(['date', ASCENDING], unique=True)
list(db.posts.index_information())

可以看到_iddate都创建了索引,前面是数据库自动创建的。nique index不能出现重复的值。当插入的记录在建索引的field出现重复值时,会出现错误提示:

oldpost = db.posts.find_one()
newpost = oldpost.copy()
newpost['author'] = 'Green'
db.posts.insert_one(newpost)
# raise DuplicateKeyError(error.get("errmsg"), 11000, error)

参考:

PyMongo Document
MongoDB 3.4 Manual