Python中使用MongoEngine1
pymongo来操作MongoDB数据库,但是直接把对于数据库的操作代码都写在脚本中,这会让应用的代码耦合性太强,而且不利于代码的优化管理
一般应用都是使用MVC框架来设计的,为了更好地维持MVC结构,需要把数据库操作部分作为model抽离出来,这就需要借助MongoEngine
MongoEngine是一个对象文档映射器(ODM),相当于一个基于SQL的对象关系映射器(ORM)
MongoEngine提供的抽象是基于类的,创建的所有模型都是类
安装
pip install mongoengine
使用时先声明一个继承自MongoEngine.Document的类
在类中声明一些属性,相当于创建一个用来保存数据的数据结构,即数据已类似数据结构的形式存入数据库中,通常把这样的一些类都存放在一个脚本中,作为应用的Model模块
from mongoengine import *
connect('test', host='localhost', port=27017)
import datetime
class Users(Document):
name = StringField(required=True, max_length=200)
age = IntField(required=True)
users = Users.objects.all() #返回所有的文档对象列表
for u in users:
print("name:",u.name,",age:",u.age)
保存文档
from mongoengine import *
connect('test', host='localhost', port=27017)
import datetime
class Users(Document):
name = StringField(required=True, max_length=200)
age = IntField(required=True)
user1 = Users(
name='zz',
age= 11
)
user1.save()
print(user1.name)
user1.name = 'zz11'
user1.save()
print(user1.name)
查询10=<年龄<30的,按姓名排列
from mongoengine import *
connect('test', host='localhost', port=27017)
import datetime
class Users(Document):
name = StringField(required=True, max_length=200)
age = IntField(required=True)
user_search = Users.objects(age__gte=10, age__lt=33).order_by('name')
for u in user_search:
print("name:",u.name,",age:",u.age)
查询10=<年龄<30的,按姓名倒序
from mongoengine import *
connect('test', host='localhost', port=27017)
import datetime
class Users(Document):
name = StringField(required=True, max_length=200)
age = IntField(required=True)
user_search = Users.objects(age__gte=10, age__lt=33).order_by('-name')
for u in user_search:
print("name:",u.name,",age:",u.age)
查询name=zz11
from mongoengine import *
connect('test', host='localhost', port=27017)
import datetime
class Users(Document):
name = StringField(required=True, max_length=200)
age = IntField(required=True)
tmp = Users.objects(name="zz11")
for u in tmp:
print("name:",u.name,",age:",u.age)
修改name=zz11的age加1
from mongoengine import *
connect('test', host='localhost', port=27017)
import datetime
class Users(Document):
name = StringField(required=True, max_length=200)
age = IntField(required=True)
tmp = Users.objects(name="zz11").update(inc__age=1)
tmp = Users.objects(name="zz11")
for u in tmp:
print("name:",u.name,",age:",u.age)
修改name=zz11的age设为55
from mongoengine import *
connect('test', host='localhost', port=27017)
import datetime
class Users(Document):
name = StringField(required=True, max_length=200)
age = IntField(required=True)
tmp = Users.objects(name="zz11").update(set__age=55)
tmp = Users.objects(name="zz11")
for u in tmp:
print("name:",u.name,",age:",u.age)
Python中使用MongoEngine2
mongoengine基本用法实例:
from mongoengine import *
from datetime import datetime
#连接数据库:test
# connect('test') # 连接本地test数据库
connect('test', host='127.0.0.1', port=27017, username='test', password='test')
# Defining our documents
# 定义文档user,post,对应集合user,post
class User(Document):
# required为True则必须赋予初始值
email = StringField(required=True)
first_name = StringField(max_length=50)
last_name = StringField(max_length=50)
date = DateTimeField(default=datetime.now(), required=True)
# Embedded documents,it doesn’t have its own collection in the database
class Comment(EmbeddedDocument):
content = StringField()
name = StringField(max_length=120)
class Post(Document):
title = StringField(max_length=120, required=True)
# ReferenceField相当于foreign key
author = ReferenceField(User)
tags = ListField(StringField(max_length=30))
comments = ListField(EmbeddedDocumentField(Comment))
# 允许继承
meta = {'allow_inheritance': True}
class TextPost(Post):
content = StringField()
class ImagePost(Post):
image_path = StringField()
class LinkPost(Post):
link_url = StringField()
# Dynamic document schemas:DynamicDocument documents work in the same way as Document but any data / attributes set to them will also be saved
class Page(DynamicDocument):
title = StringField(max_length=200, required=True)
date_modified = DateTimeField(default=datetime.now())
添加数据
john = User(email='john@example.com', first_name='John', last_name='Tao').save()
ross = User(email='ross@example.com')
ross.first_name = 'Ross'
ross.last_name = 'Lawley'
ross.save()
comment1 = Comment(content='Good work!',name = 'LindenTao')
comment2 = Comment(content='Nice article!')
post0 = Post(title = 'post0',tags = ['post_0_tag'])
post0.comments = [comment1,comment2]
post0.save()
post1 = TextPost(title='Fun with MongoEngine', author=john)
post1.content = 'Took a look at MongoEngine today, looks pretty cool.'
post1.tags = ['mongodb', 'mongoengine']
post1.save()
post2 = LinkPost(title='MongoEngine Documentation', author=ross)
post2.link_url = 'http://docs.mongoengine.com/'
post2.tags = ['mongoengine']
post2.save()
# Create a new page and add tags
page = Page(title='Using MongoEngine')
page.tags = ['mongodb', 'mongoengine']
page.save()
创建了三个集合:user,post,page
查看数据
# 查看数据
for post in Post.objects:
print post.title
print '=' * len(post.title)
if isinstance(post, TextPost):
print post.content
if isinstance(post, LinkPost):
print 'Link:', post.link_url
# 通过引用字段直接获取引用文档对象
for post in TextPost.objects:
print post.content
print post.author.email
au = TextPost.objects.all().first().author
print au.email
# 通过标签查询
for post in Post.objects(tags='mongodb'):
print post.title
num_posts = Post.objects(tags='mongodb').count()
print 'Found %d posts with tag "mongodb"' % num_posts
# 多条件查询(导入Q类)
User.objects((Q(country='uk') & Q(age__gte=18)) | Q(age__gte=20))
# 更新文档
ross = User.objects(first_name = 'Ross')
ross.update(date = datetime.now())
User.objects(first_name='John').update(set__email='123456@qq.com')
//对 lorem 添加商品图片信息
lorempic = GoodsPic(name='l2.jpg', path='/static/images/l2.jpg')
lorem = Goods.objects(id='575d38e336dc6a55d048f35f')
lorem.update_one(push__pic=lorempic)
# 删除文档
ross.delete()
备注
ORM全称“Object Relational Mapping”,即对象-关系映射,就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码更简单,不用直接操作SQL语句。
Python中使用MongoEngine3
最近重新拾起Django,但是Django并不支持mongodb,但是有一个模块mongoengine可以实现Django Model类似的封装.但是mongoengine的中文文档几乎没有,有的也是简短的几句介绍和使用.下面我就分享一下我在使用过程中所记录下的一些笔记,可能有点乱.大家可以参考一下.
安装mongoengine
easy_install pymongo # 依赖库
easy_install mongoengine
基本使用
from mongoengine import *
from datetime import datetime
# 连接数据库
connect('blog') # 连接本地blog数据库
# 如需验证和指定主机名
# connect('blog', host='192.168.3.1', username='root', password='1234')
# 定义分类文档
class Categories(Document):
' 继承Document类,为普通文档 '
name = StringField(max_length=30, required=True)
artnum = IntField(default=0, required=True)
date = DateTimeField(default=datetime.now(), required=True)
和Django的model使用很类似,所以也不解释什么.
插入
cate = Categories(name="Linux") # 如果required为True则必须赋予初始值,如果有default,赋予初始值则使用默认值
cate.save() # 保存到数据库
查询和更新
文档类有一个 objects 属性.我们使用它来查询数据库.
# 返回集合里的所有文档对象的列表
cate = Categories.objects.all()
# 返回所有符合查询条件的结果的文档对象列表
cate = Categories.objects(name="Python")
# 更新查询到的文档:
cate.name = "LinuxZen"
cate.update()
查询数组 默认查询数组"="代表的意思是in:
class Posts(Document):
artid = IntField(required=True)
title = StringField(max_length=100, required=True)
content = StringField(required=True)
author = ReferenceField(User)
tags = ListField(StringField(max_length=20, required=True), required=True)
categories = ReferenceField(Categories), required=True)
comments = IntField(default=0, required=True)
# 将会返回所有tags包含coding的文档
Posts.objects(tags='coding')
ReferenceField 引用字段:
通过引用字段可以通过文档直接获取引用字段引用的那个文档:
class Categories(Document):
name = StringField(max_length=30, required=True)
artnum = IntField(default=0, required=True)
date = DateTimeField(default=datetime.now(), required=True)
class Posts(Document):
title = StringField(max_length=100, required=True)
content = StringField(required=True)
tags = ListField(StringField(max_length=20, required=True), required=True)
categories = ReferenceField(Categories)
插入引用字段
cate =Categories(name="Linux")
cate.save()
post = Posts(title="Linuxzen.com", content="Linuxzen.com",tags=["Linux","web"], categories=cate)
post.save()
通过引用字段直接获取引用文档对象
一般文档查询会返回一个列表(尽管只有一个结果),我们想要获得一个文档对象可以使用索引获取第一个文档对象,但是mongoengine建议使用first()来获取第一个:
>>> cate = Posts.objects.all().first().categories
>>> cate
>>> cate.name
u'Linux'
查询包含Linux分类的文章
>>> cate = Categories.objects(name="Linux").first()
>>> Posts.objects(categories=cate)
EmbeddedDocument 嵌入文档
继承EmbeddedDocument的文档类就是嵌入文档,嵌入文档用于嵌入其他文档的EmbeddedDocumentField 字段,比如上面例子的tags字段如果改成嵌入文档的话可以将Posts文档类改成如下方式:
class Posts(Document):
title = StringField(max_length=100, required=True)
content = StringField(required=True)
tags = ListField(EmbeddedDocumentField('Tags')required=True)
categories = ReferenceField(Categories)
还需要添加一个Tags嵌入文档类:
class Tags(EmbeddedDocument):
name = StringField()
date = DateTimeField(default=datetime.now())
我们像如下方式插入Posts文档中的Tags
>>> tag = Tags(name="Linuxzen")
>>> post = Posts(title="Linuxzen.com", content="Linuxzen.com", tags=[tag], categories=cate)
>>> tag = Tags(name="mysite")
>>> post.tags.append(tag)
>>> post.save()
>>> tags = post.tags
>>> for tag in tags:
print tag.name
Linuxzen
mysite
时间段查询
start = datetime(int(year), int(month), 1)
if int(month) + 1 > 12:
emonth = 1
eyear = int(year) + 1
else:
emonth = int(month) + 1
eyear = int(year)
end = datetime(eyear, emonth, 1)
articles = Posts.objects(date__gte=start, date__lt=end).order_by('-date')
分片
slice用于分片
# comments - skip 5, limit 10
Page.objects.fields(slice__comments=[5, 10])
# 也可以使用索引值分片
# limit 5
users = User.objects[:5]
# skip 5
users = User.objects[5:]
# skip 10, limit 15
users = User.objects[10:15]
使用原始语句查询
如果想使用原始的pymongo查询方式可以使用__raw__操作符 Page.objects(raw={‘tags’:‘coding’}) 使用 i n c 和 inc和 inc和set操作符
# 更新嵌入文档comments字段by的值为joe的文档字段votes增加1
Page.objects(comments_by="joe").update(inc__votes=1)
# 更新嵌入文档comments字段by的值为joe的文档字段votes设置为1
Page.objects(comments_by="joe").update(set__votes=1)
其他技巧
#查询结果转换成字典
users_dict = User.objects().to_mongo()
# 排序,按日期排列
user = User.objects.order_by("date")
# 按日期倒序
user = User.objects.order_by("-date")