zope3的mongodb连接池和容器实现

m01.mongo的Python项目详细描述


这个包提供了一个mongodb对象映射器框架,包括基于一些核心zope组件库的zope
事务支持。这个包
可以与zope一起使用,也可以不使用zope.persistent,它可以完全替代
zodb。基于zope本身,这个包并不重,可以用于任何需要从mongodb到python对象的桥的python项目。



=
=
readme
=



重要的是:
如果使用--all选项运行测试,真正的mongodb存根服务器将从端口45017启动!

此包提供非持久的MongoDB对象实现。如果您想在混合mongodb/zodb应用程序设置中使用它们,可以将它们与persistent.persistent和contained.contained混合使用。我们目前使用这个
框架作为orm(对象关系映射器),在这里我们将mongodb对象
映射到基于python/zope架构的对象,包括验证等。

在上一个项目中,我们从一个混合的zodb/mongodb应用程序开始,在这里我们将
混合的persistent.persistent映射到imongcontainer对象。但后来我们发现
对性能和稳定性的要求太高,以至于我们完全删除了zodb
持久层。现在我们在应用程序中使用一个无zodb的设置
,从一个非持久项开始作为应用程序根。我们用于这种无zodb应用程序设置的所有必需的
工具都位于
p01.publisher和p01.recipe.setup包中。

注意:有些测试使用位于m01/mongo/testing中的假mongodb,而有些
其他测试将使用m01.stub包中的mongdb存根。如果您想运行完整的测试,可以使用--all选项运行
测试,该测试将
启动和停止MongoDB存根服务器。

注意:
所有Mongo项接口都不会提供iLocation或iContained,但是
基本Mongo项实现将实现直接提供
iLocation接口的位置。这使得zcml中的权限声明变得更简单。



setup
----

>;>;import pymongo
>;>;import zope.component
>;>;from m01.mongo import interfaces


----

setup一个mongo客户端:

>;客户=PyMongoo.Mongoclient('localhost',45017)
>gt>gt;客户
>Mongoclient(host=[127.0.0.0.1:45017'])




>正如您所见,Mongoclient(host=[127.0.0.0.0.0.0.0.1:45017']>mongoclient(host=[127.0.0.0.0.0.0.0.0.0.0.1:45017']>Mongoclient(host=[127.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0/>
数据base可以重新运行集合:

>;>collection=db['m01mongotest']
>;>collection
集合(数据库(mongoclient(host=['127.0.0.1:45017']、u'm01mongotesting')、u'm01mongotest')

{'$inc':{'counter':1}},
…upsert=true)
>>gt;res
<;pymongo.results.updateresult object at…>;
>
>;res.raw-result
{{updatedesult object at…>;
>;res.raw-result
{{updatedeexisting':false,'nmmodified':0,'ok':1,'upserted':'123''123','n''123''123':1}




>
>
>>>>>;collection;collection;collection;collection;collection;collection;col/>{u"id":u'123',u'counter':1}


从我们的测试集合中删除结果:

>;>res=集合。删除一个({''u id':'123'})
>;>res
<;pymongo.results.deletereresult object at…>;

>;>res.raw\result
{ok':1,"n":1}





>










>现在就把我们的MongoDB数据库和我们当前的MongoDB连接一起拆了:

>>>gt;导入时间
>gt;时间。睡眠(1)
>>>
>>
>>客户端。下拉式数据库('M01MongoMongootesting')


>
==========

>>

>>


=====>

======

MongoContainer可以在MongoDB中存储ImongoContainerElem对象。a
MongoContainerItem必须能够将其数据转储到有效的MongoDB数据。此
测试将显示MongoContainer的工作原理。



条件
——


>首先导入一些组件:

>;>import json
>;>import transaction
>;>import zope.interface
>;>import zope.schema
>;<>;import m01.mongo.item
>;>import m01.mongo.testing
>;>from m01.mongo.fieldproperty import mongofieldproperty
>;>from m01.mongo import interfaces

一些来自以前测试的垃圾:

>;>from m01.mongo import local
>;>m01.mongo.testing.pprint(local.\uu dict\uu)
{}




set up
-


并设置数据库根目录:

>;root={}


--——————————————————————————————————————————————————————————————————————zope.location.interfaces.ilocation:
…""示例项接口。""

…title=zope.schema.textline(
…title=u'object title',
…description=对象标题,
…必需=真)



>>>>类SampleContainerItem(m01.mongo.item.mongoContainerItem):
…""样品容器项目"

…zope.interface.implements(isSampleContainerElem)

…title=mongofieldproperty(isamplecontaineritem['title'])

…dumpnames=['title']



MongoContainer
----

>;>类是示例容器(interfaces.imongContainer):
…""示例容器接口。"类SampleContainer(m01.mongo.container.mongoContainer):
…"样本容器。""

…zope.interface.implements(isamplecontainer)

…@属性
…def收集(自身):
…db=m01.mongo.testing.getTestDatabase()
…返回db['test']

…def load(self,data):
…""将数据加载到右边的mongo项中。""
…返回samplecontaineritem(data)

>;>container=samplecontainer()
>;>root['container']=container




>;>;data={'title':u'title'}
>;>;item=samplecontaineritem(data)
>;>;container=root['container']
>;>;container[u'item']=item

transaction
----

zope为数据库中的存储对象提供事务。我们还提供
这样的事务和事务数据管理器,用于将我们的对象存储在
mongodb中。这意味着现在测试数据库中不会存储任何内容,因为
我们没有提交事务:

>;>;collection=m01.mongo.testing.getTestCollection()
>;>;collection.count()
0

ngodb:

>;>transaction.commit()

>;>collection=m01.mongo.testing.gettestcollection()
>;>collection.count()
1

数据
>



正如您所看到的,以下数据存储在我们的MongoDB中:


>gt>gt;data=collection.data=collection.data=collection.fin找到一个({'''u name''item''item'}
>>gt>gt;m01.mongo.mongo.testing.ppprint(data)数据

{{{u name''u'item''u'item',
u'id''u id''id'''''''''…''''''''>
u'u'''''u''''''''''PID':无,
u"类型":u"sampleContainerTime",
u"版本":1,
u"创建":datetime.datetime(…,tzinfo=utc),
u"修改":datetime.datetime(…,tzinfo=utc),
u"标题":u"标题"}


来自MongoDB的数据:

>;>obj=container[u'item']
>;obj
<;samplecontaineritem u'item'>.mongo导入clearthreadlocache
>;>;clearthreadlocache()


/>====


MongOStorage可以在MongoDB中存储imongostorageitem对象。a
MongoStorageTime必须能够将其数据转储为有效的Mongo值。这个
测试将显示我们的MongoStorage是如何工作的,同时也显示了它的局限性。

注意:Mongo容器还实现了一个容器/映射模式,如
存储实现。唯一的区别是,容器仅使用contaner[key]=obj、container[key]和del container[key]提供
映射api。
存储api不提供显式映射键,而是提供add和remove
方法。这意味着容器使用它自己的命名模式,
存储使用mongodb.\u id作为对象名(obj.\u name)。



condition
--


测试:

>;>from m01.mongo import local
>;>from m01.mongo.testing import pprint
>;>pprint(local.\uu dict\uu)
{}



setup
----


first import some components:
>;>;>;>>;>从m01.mongo导入接口
>;>从m01.mongo导入测试

并设置数据库根:

>;>根={}


---——

默认情况下,mongo项提供一个存储为"id"的objectid。如果在创建对象过程中没有给定对象,我们将设置一个:

>;>;>obj=testing.samplestorageitem(data)
>;>obj.objectid('…')

tobjectid也用作我们的名字值。如果需要选择自己的名称,请参阅MongoContainer和MongoContainerItem实现:


>;>obj.\u u name\uu'…'

>;>obj.\uu name\uu==Unicode(obj.&u id)
true

如果在没有给定创建日期的情况下初始化对象,则使用新的UTC日期时间实例



>;>;obj.created
datetime.datetime(…,tzinfo=utc)


>;>;obj.modified为none
true

mongo存储项知道状态是否发生更改。这意味着我们可以找出
是否应该将项目写回MongoDB。mongoitem将状态
存储在一个已更改的值中,就像持久对象在已更改的值中所做的那样。如您所见,
初始状态是``none`:

>;>obj.\u m_changed is none
true

mongoitem也有一个版本号,我们每次更改
项时都会增加该版本号。默认情况下,此版本设置为"版本"属性,并由
默认值设置为0(零):

>;>;obj.&u version
0


bj.\u m_已更改
true


,但版本未被修改。我们只在mongodb中保存
项目时才修改版本:

>;0

r/>>;>;obj.title
u'

>;>;obj.title=u"新标题"
>;>;obj.title
true

>;>;obj.title
u"新标题"

_ m_changed=false
>;>;obj.&u m_changed
false

>;>;del obj.title

这似乎很好。

>;>obj.title
u'


>;>obj.u.已更改



mongostorage
----

torage']=storage
>;>transaction.commit()

注意,我们只能使用
add方法返回新生成的名称。此实现不支持使用自己的名称。如您所见,名称是MongoDB
24十六进制字符串objectid表示。

>;>;data={'title':u'title',
…'description':u'description'}
>;>item=测试。sampleStorageitem(数据)
>;>storage=root['storage']


>我们的存储提供imongostorage和ireadcontainer接口:

>;>interfaces.imongostorage.providedby(storage)
true

>>gt;ireadcontainer。providedby(存储)providedby(存储)
>true





>







>我们可以使用add方法将mongo项添加到存储中。使用add方法可以将mongo项添加到存储中。

>>gt>gt;
>u-name\u'>>u'>>
>>>>>>>>
>>>>>>>>>>>>u-name
>u'>>u'>>u'>>>u'>>>>>
>>>>>>>>>>>>>>>24

>;>;transaction.commit()

年龄)
1



我们可以把这个东西扔了。注意,您可能必须实现一个自定义转储方法,该方法将
为您的MongoStorageitem转储正确的数据。


>;>pprint(item.dump())
{"uu name":"…",
"u id":objectid("…"),
"u pid":none,
"u type":"sampleStorageitem",
"u version":1,"注释":[],
"创建":datetime.datetime(…,tzinfo=utc),
"日期":无,
"说明":"说明",
"项目":无,
"修改":datetime.datetime(…,tzinfo=utc),
"编号":无,
"编号":[],
"标题":"标题"}

t还提供了一个名称,这是我们在添加
对象时得到的名称:

>;>;项。true




keys
----


容器还可以返回key:

>;>;元组(storage.keys())
(u'…',)






/>----

容器还可以返回值:

>;>tuple(storage.values())
(<;sampleStorageitem…>;,)


----


容器还可以返回项:

>;tuple(storage.items())
((u'…',<;sampleStorageitem)…>;),)



__下一步我们将删除项:



从存储器中删除项并修改项,版本将增加一个,并设置当前修改的日期时间。


让我们添加一个新项:

>;>;data={title':u'a title',
…。说明:u'a description'}
>;>item=testing.sampleStorageitem(data)
>;>;>transaction.commit()

e'

并更改标题:

>;>;item.title=u‘new title’
>;>;item.title
u‘new title’

这应该设置为1(一),因为我们只添加了
对象,并且添加后没有更改:

>gt;项。1


>如果我们现在提交事务,则版本将增加一个:

>gt;transaction.commit()
>gt;项。rsion
2

关于
>2


>
>>transaction.commit()




>

>
>
>
>





>2






























========================

MongoContainer可以将非持久性imongocainteritem对象存储在a
mongodb中。mongocontaineritem必须能够将其数据转储到有效的mongo
值。此测试将显示MongoContainer的工作原理。


condition
----


在开始测试之前,请检查线程本地缓存是否为空,或者是否已从以前的测试中删除一些垃圾:

>;来自M01.mongo.testing import pprint
>;从m01.mongo导入local
>;>pprint(local.\uu dict
{}



setup
----


>首先导入一些组件:

>;>;>;>from zope.container.interfaces import icontainer

>;>import m01.mongo
>;>import m01.mongo.base
>;>import m01.mongo.container
>;>from m01.mongo import interfaces
>;>from m01.mongo import testing

我们还需要一个应用程序根对象。让我们定义一个静态MongoContainer
作为我们的应用程序数据库根项。

>;>Class MongoRoot(m01.mongo.container.MongoContainer):
…"Mongo应用程序根"

…_ id=m01.mongo.getobjectid(0)

…定义初始化(自身):
…通过

…@属性
…def收集(自身):
…返回testing.getrootitems()

…@属性
…def cachekey(self):
…返回"根"

…def load(self,data):
…""将数据加载到右边的mongo项中。""
…返回测试。公司(数据)

…定义代表(自我):
…返回'<;%s%s>;'%(self.\u class\uu.\u name\uu,self.\u id)



这是我们的_父项引用。



以下方法允许我们生成新的MongoRoot项实例。这使我们可以显示生成不同的根项,就像在服务器重新启动时一样。


>;>;def getroot():
…return mongoroot()

这是我们的数据库根项:

>;>root=getroot()
>;
>;root
<;mongoroot 000000000000000000000000000000>;

>;objectid('00000000000000000000000000000000')


containers
----


现在,让我们使用增强的测试数据并设置内容结构:

>;>data={'name':u'europe}
>;>europe=测试。公司(数据)
>;>root[u'europe']=europe

>;>data={'name':u'asia'}
>;>asia=testing.公司(数据)
>;>root[u'asia']=亚洲

>;>transaction.commit()

>让我们检查一下我们在Mongo的公司:

>;>rootcollection=testing.getrootitems()
>;>obj=rootcollection.find懔one({'name':'europe'})
>;>亲亲(obj)
{u'u欧洲',
u'u id':objectid("…"),
u'u id':objectid("…"),
u'u pid':objectid("…"),
u'u类型:u'u公司',
u'u版本:1,
u'created':datetime.datetime(…,tzinfo=UTC),
u'moded':datetime.datetime(…,tzinfo=utc),
u'created':datetime.datetime.datetime(…,tzinfo=utc),
u'u'created':datetime.datetime.datetime(…,t'}

现在,让我们添加一个公司、雇主和一些文档:

>;>data={'name':u'projekt01 GmbH'}
>;>pro=测试。公司(数据)
>;>europe[u'pro']=pro
>;>data={'name':u'roger ineichen'}
>;>roger=testing.employer(data)
>;>pro[u'roger']=roger

>;>data={'name':u'manual'}
>;>manual=testing.document(data)
>;>roger[u'manual']=manual

>;>transaction.commit()

真正使用我们的容器,物品对象:

>;
>;根['europe']
<;公司u'europe'>;

>;>;根['europe']['pro']
<;公司u'pro'>;

>;>;根['europe']['pro']['roger']
<;雇主u'roger'>;

>;根目录['europe']['pro']['roger']['manual']
<;document u'manual'>;

您可以看到,此结构与其父目录相关。这意味着如果我们将另一个结构添加到同一个MongoDB中,每个项目都知道它是
容器。

>;data={'name':u'credit suisse'}
>;>cs=testing.company(data)
>;>asia[u'cs']=cs

>;data={'name':u'max muster'}
>>gt;max=测试。雇主(数据)
>>cs[u'max']=max

>;>;数据={'name':u'paper'}
>;>;纸张=测试。文档(数据)
>;>;max[u'paper']=纸张

>;>;事务处理.commit()

>;>;根['a
<;亚洲企业;

>
>;亚洲企业的根['亚洲]['cs']
<;亚洲企业的根['cs'>


>
>
>;亚洲企业的根['亚洲]['cs']['max']
<;亚洲企业的根['cs']['cs']['max'>
>
>
>;亚洲企业的根['亚洲]['cs']['max'']['max''''><;亚洲企业的根['亚洲企业的根['亚洲企业的根]['cs'['cs']['max'']['max'']['max'''"纸张">;

从另一个父容器访问同一类型的另一个项:

>;>root['europe']['cs']
traceback(最近一次调用):

keyrerror:'cs'

>;>transaction.commit()

OCache高速缓存。我们可以使用我们的线程本地缓存清理事件处理程序(默认情况下注册为endrequestevent订阅服务器)来清理我们的线程本地缓存:

>;>pprint(local.\u u dict
{u'europe':{loaded':{},'removed':{}}

使用我们的订阅服务器:

>;>;来自M01。Mongo导入ClearThreadLocalCache
>;>;ClearThreadLocalCache()

/>共享容器
----


现在让我们实现一个共享容器,其中包含所有iemployer项:

>;>gt;类共享部署程序(m01.mongo.container.mongocontainer):
…"共享雇主容器"

…#通过将mpid设置为none将容器标记为shared
…_ MPID=无

…@属性
…def收集(自身):
…返回testing.getEmployers()

…def load(self,data):
…返回测试。雇主(数据)

>>>>对于shared.values()中的obj:
…pprint(obj.dump())
{"你的名字"u'roger,
"你的id":objectid("…"),
"你的pid":objectid("…",
"你的类型":u'employer,
"你的版本":1,
"创建":datetime.datetime(…,tzinfo=utc),
"修改":datetime.datetime(…,tzinfo=utc),
"名称":u'roger ineic当"}
{''''u name''u'max',
''u id':objectid('…'),
''u pid':objectid('…'),
''u type':u'employer',
''u version':1,
'创建':datetime.datetime(…,tzinfo=utc),
'修改':datetime.datetime(…,tzinfo=utc),
'名称':u'max muster'}

提交将清理缓存的事务。数据库清理工作是在我们的测试Teardown中完成的,我们的测试Teardown:

>
>>>;transaction.commit()





>
>>>>;pprint(local.\uu dict)
>















我们的线程本地缓存请在我们离开测试之前检查我们的线程本地缓存:




>





mongoobject可以与名为
mongoobject property的字段属性一起使用。field属性负责在mongodb之间设置和获取这样的
mongoobject。在mongoobjectproperty中提供这样一个
mongoobject的持久项只需要提供一个具有唯一值的oid属性
。您可以将m01.oid包用于这样一个唯一的oid
或实现自己的模式。



但这个假服务器离beeing complete还远着呢。如果
在其他项目中需要,我们将向这个假服务器添加更多功能。有关详细信息,请参见testing.py。



条件
——


在开始测试之前,请检查线程本地缓存是否为空,或者是否已从以前的测试中删除一些垃圾:


>;>;来自m01.mongo。testing import pprint
>;>;来自m01.mon转到导入本地
>;>pprint(本地。
{}



setup
----


>首先导入一些组件:

>;>import datetime
>;>import transaction
>;>from m01.mongo import interfaces
>;>from m01.mongo导入测试

首先,我们需要设置一个持久对象:

>;>;content=testing.content(42)
>;>;content.\u moid
42


并将它们添加到zodb:

>;>;root={}
>;>;root['content']=content
>;>;transaction.commit()

>;>content=root['content']
>;>content
<;content 42>;



mongoobject
------

现在,让我们将mongo object实例添加到示例内容对象:

>;>;data={title':u'mongo object title',
…。描述:u'a description',
…项目':{'text':u'item'},
…'日期:datetime.date(2010,2,28).toordinal(),
…数字':[1,2,3],
…'注释':[{'text':u'comment 1'},{'text':u'comment 2'}}
>;>obj=测试。samplemongoobject(数据)
>;>obj。objectid("…")

u'mongo object title

>;u'a description'

>;>"obj.obj.obj.obj.obj.obj.obj.obj.obj.obj.obj.obj.obj.obj.obj.obj.编号


>
>>>
>>>>

[1,2,3]
>
>>>>obj.obj.obj.obj.评论
[<;samplesubitem u'''>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>元组(obj.comments)[0].text
u'comment 1'

>
>gt>gt>>元组(obj.comments)[1].text
>u'comment 2'


>
>我们的mongoooobject现在还没有提供一个或一个名称或一个名称的对象:


>>
>gt>>>
>obj。

>true
>
>>br/>>>>>>>
>>>>>>obj。
>
>>
>>>>>>>>>>>>>>>>>>>>>>>
>>obj。
>u0不是
真的

在将mongo对象添加到使用
mongoobjectproperty的内容之后,mongo对象将被定位并成为属性
name作为字段值。如果对象没有提供一个名称,则相同的值
>也将应用于名称:obj;content.obj=obj;obj;obj;obj;content.obj=obj;obj;obj;obj;obj;content.obj;content 42>;
>
>
>obj;obj;obj;obj;obj;content 42>;content 42>;content 42>;content 42>;content 42>;

>
>obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;obj;目标名称/>
添加mongo对象后,线程本地缓存中应该有一个引用:

>;>;pprint(local.\u u dict\uu)
{u'42:obj':<;samplemongoobject u'obj'>;,
'mongotransactiondatamanager':<;m01.mongo.tm.mongotransactiondatamanager对象位于…>;}

mongoobject提供一个用作mongodb键的oid属性。这个
值使用moid和mongo object s属性名:


>值:

>br/>>gt>gt;obj=content.obj
>gt>gt;obj.title
u'mongoo objecttitle

>
>>>
>>>>obj.obj.description
>u'a description'

>>
>
>
>
>
>
>
>
>u'item u'>
>>
>>>
>>>>>>>obj.obj.obj.obj.item
>u'item u'item'>u'item'>
>u'/>
>>>gt>gt;obj.数
[1,2,3]


>>gt>gt;obj.数
[>
[<;samplesubitem u'…'>>gt;,<;samplesubitemu'…''>>br/>
>
>>>gt>gt;元组(obj.注释)[0].text
>u'comment 1'
>br/>>
>>>gt;元组(obj.注释)[1].text
>u'comment 2'>>u'comment2''>>u'comment2''>
>>
>
>>br/>>>

现在让我们提交将obj存储在我们的假mongo数据库中的事务:

>;>;transaction.commit()

;pprint(local.\uu dict\uu)
{}


现在再次检查我们的mongo对象值。如果您的内容项存储在
zodb中,您将从zodb连接根目录中获取该内容项:

>;>content=root['content']
>;>content
<;content 42>;

>;>obj=content.obj
>;<;samplemongoobjec不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产不动产.数字
[1,2,3]

>>> obj.comments
[<SampleSubItem u'...'>, <SampleSubItem u'...'>]

>>> tuple(obj.comments)[0].text
u'Comment 1'

>>> tuple(obj.comments)[1].text
u'Comment 2'

>>> pprint(obj.dump())
{'__name__':U Obj',
u field':u obj',
u id':obj id(……),
u oid',
u oid':U42:obj,
uype型:U samplemongoooobject',
u version:1,
br/>comments:[{{{br/>obj id>subject:[>subject:[>subject:["',
created':datetime.datetime(…),
modified:'none,
text:` u comment 1',
{id:` objectid'(…),br/>u type:` u samplesubitem',br/>created:` datetime.datetime(…),br/>modified:none,
text/>
created':datetime.datetime(……),date
date>date>733831,
description>:u'a description',br/>idem:{objectid(……),br/>type:u samplesubitem,
created dateme
,non/>。Text':U item',
modified':datetime.datetime(……),
number>none:none,
numbers:[1,2,3],
removed:false,
title:U Mongo object title>br/>br/>br/>br/>gt>>>transaction
br/>br/>br/>br/>br/>GT;PPRINT(Local.)

now让我们用一个新的项目代替现有的项目,并将另一个项目添加到项目清单上。另一方面,确保我们能够使用《全面执行公约》的手段
list like zope widgets do:

br/>br/>br/>gt> content=root[>content=root[>content]
gt>>=gt=obj
br/>br/>gt>>>&test m=subbite

gt>>=testing.SampleSubItem({'text': u'New List Item'})
>>> obj.comments.append(newItem)

>>> obj.numbers.append(4)

>>> transaction.commit()

check again:

>>> content = root['content']
>>> obj = content.obj

>>> obj.title
u'Mongo Object Title'

>>> obj.description
u'A Description'

>>> obj.item
<SampleSubItem u'...'>

>>> obj.item.text
u'New Item'

>>> obj.numbers
[1, 2, 3, 4]>>>
>>>>
>[>>>>>>>>>>>>>[>>>>[>>>[>br/>>br/>gt>>>>>
gt>>>>>tuple(obj.comments>>u>bur/>1 comment>
>>2.comments[1].text
u comment 2
and now re-apply a full list of values to theList field:

>br/>>>>br/>>>>>gt>>&comcomtwo=testing.samplesubitem(
gt>>>>>>>
gt&t&two gt>br/>gt>>gt>gt>gt>gt>>gt>gt>>>.comments=comments
>>.numbers = [1,2,3,4,5]
>>> transaction.commit()

check again:

>>> content = root['content']
>>> obj = content.obj

>>> len(obj.comments)
2

>>> obj.comments
[<SampleSubItem u'...'>, <SampleSubItem u'...'>]

>>> len(obj.numbers)
5

>>> obj.numbers
[1, 2, 3, 4, 5]

Also check if we can remove list items:

>>> obj.numbers.remove(1)
>>> obj.numbers.remove(2)

>>> obj.comments.remove(comTwo)

>>> transaction.commit()

check again:

>>> content = root['content']
>>> obj = content.obj

>>> len(obj.comments)
1

>>> obj.comments
[<SampleSubItem u'...'>]
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>;;;;;>>>>;> >>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< >> obj = content.obj

>>删除对象对象对象注释[对象名称]

>
>>>>事务处理提交(transaction.commit)


>再次检查:

>>>>>gt;content=root['content']
>>>;obj=content.obj=content.obj

>>
>>>>>>>>>>len(对象注释)
>0
>
>>
>
>

>

>

>

>

>

>


>

<>> > > transaction.commit ()<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>;> comments [comOne...] You can make a name ========= <<<<<<

check aga在:

>;>content=root['content']
>;>obj=content.obj

>;>len(obj.comments)
1

>;[<;samplesubitem u'…'>;]

>;transaction.commit()


/><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>> comOne.<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<(comOne.
<SampleSubItem u'...'>
><<<<<<<&&>&> comments.comments.keys () == [comone.<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>> obj.comments.items ()
<generator object object...><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<&&>&&&>; > comments comments ==submsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmsubmobjects(((((()))<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> > > > >Traceback (most recent call last last):<
...<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
AttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrAttrchangechange change change change change change change change change change change change change change change change change change change change change change change last last last last last last last last last last last last last call last last last last last last last last last last last last last last last last last last last last last last last last last last last last last last last <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;>>locate.locate <<<<<<<>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>;;;;; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
True

>>> obj.numbepop ()<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>&>&&>&>&>&>>>>>; and and and you changed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>> obj.numbersThe Traceback (most recent call last):<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>> &>>>>>>>>>>>; ><<<<<<<<< >>>><<<<<>==========
GeoLocation
==========References =====

地理位置项可以存储地理位置,并作为提供经度和纬度的子项在项中使用。除了此
字段之外,地理位置还提供了更改的调度概念,并且能够在lon/lat发生更改时
通知外部父项。该项还为安全查找支持提供
ilocation。field属性负责
应用

geolocation项支持经度、纬度的顺序并保留它们。



条件
----


在开始测试之前,请检查线程本地缓存是否为空或是否有
let o从以前的测试中发现一些垃圾:

>>>>来自M01.mongo.testing import pprint
>;>来自M01.mongo.testing import renormalizer
>;>来自M01.mongo.testing import renormalizer
>;>pprint(local.\uu dict\uu)
{


setup
----

;导入日期时间
>;>导入事务

>;>导入M01.mongo
>;>导入M01.mongo.base
>;>导入M01.mongo.geo
>;>导入M01.mongo.container
>;>从M01.mongo导入接口
>;>从m01.mongo导入测试

我们还需要一个应用程序根对象。让我们定义一个静态MongoContainer
作为我们的应用程序数据库根项。

>;>Class MongoRoot(m01.mongo.container.MongoContainer):
…"Mongo应用程序根"

…_ id=m01.mongo.getobjectid(0)

…定义初始化(自身):
…通过

…@属性
…def收集(自身):
…返回testing.getrootitems()

…@属性
…def cachekey(self):
…返回"根"

…def load(self,data):
…""将数据加载到右边的mongo项中。""
…返回测试。地理样本(数据)

…定义代表(自我):
…返回'<;%s%s>;'%(self.\u class\uu.\u name\uu,self.\u id)



这使我们可以显示生成不同的根项,就像在服务器重新启动时一样。


>;>;def getroot():
…return mongoroot()

这是我们的数据库根项:

>t设置索引:

>;>collection=testing.getrootitems()

>;>from pymongo import geo2d
>;>collection.create_index([('lonlat',geo2d)]
u'lonlat_2d'


geosample
--

lon/lat值列表中的位置
或lon/lat dict中的位置:

>>;数据={'name':u'sample','lonlat':{'lon':1,'lat':3}
>;>;样本=测试。地理样本(数据)
>;>;样本。lonlat
<;地理位置lon:1.0,lat:3.0>;

>;>;data={'name':u'sample','lon lat':[1,3]}
>;>sample=testing.geosample(data)
>;>sample.lonlat
<;geolocation lon:1.0,lat:3.0>;

>;>root[u'sample']=sample

>;transaction.commit()

蒙哥的em:mongo中的m:

>>>gt;data=colcollection.find-one({'name':'sample''sample'}
>>gt>gt;renormalizer.ppprint(data)
{u'sample''u'sample',
u'u id':objectid("…"),
u'u id''u'u id'",
u'u id':objectid("…"),
>u'u id'''",
>u'u'geossample',
>u'u'ussample',
u'u'u'version':u'u'u'1,
u"创建":datetime.datetime(…,tzinfo=utc),
u'lon lat':[1.0,3.0],
u'modified':datetime.datetime(…,tzinfo=utc),
u'name':u'sample'}

>我们还可以将地理位置用作lonlat数据:

>;geo=m01.mongo.geo.geo.geo.geolocation({u'lat':4,u'lon':2}
>>t;data={'name':u'sample2','lonlat':geo}
>;>>;sample2=测试。geosample(data)
>;>>;root[u'sample2']=sample2

>;>;transaction.commit()

>;>;data=集合。查找一个({'name':'sample2'})
>;>;renormalizer.pprint(数据)
{u"name":u"sample2"、
u"id":objectid("…")、
u"pid":objectid("…")、
u"type":u"geosample"、
u"version":1、
u'创建时间:datetime.datetime(…,tzinfo=utc),
u'lon lat':{u'lat':4.0,u'lon':2.0},
u'modified':datetime.datetime(…,tzinfo=utc),
u'name':u'sample2'}



>>gt;geo=m01.mongo.geo.geo.geo.geo.geo定位({'lon':4,'lat':6})
>>>gt;sample2.lonlat=geo
>
>>>>>gt;transaction.commit()
>
>>>gt;data=collection.data=collection.fin一个({'name''sample2'})
>gt>gt;renormalizer.ppprint(数据)
>
{u'sample2.pusample2.pprint(数据)

>>>
{u'u'sample2.pusample2.pu',
u-id:objectid("…"),
u-pid:objectid("…"),
u-u类型:u'geossample,
u版本:2,
u'created':datetime.datetime(…,tzinfo=UTC,
u'lon lat':{u'lat'u'lat':6.0,u'lon':4.0},
u'moded':datetime.datetime(…,tzinfo=UTC,
u'name':u'sampleplesample':u'geossample',
u'u版本:2,
u'u'u'u'u-version':2,
2英尺}



搜索
----


让我们测试一些地理位置搜索查询,并确保我们的lon/lat订单
在MongoDB往返过程中适合并保留。


现在请查看地理位置搜索:

>;def printfind(集合,查询):
…对于collection.find(查询)中的数据:
…ppprint(data)



>利用地理空间索引,我们可以在另一个点附近找到文档:printfind(collection,{'lonlat':{'lonlat':{'$near':[0,2]})
(collection,{'lonlat'lonlat':{'lonlat':[0,2]})
{{u''u'u'u'u'sample',
u'u'u id':objectid("…"),
u'u'u id':objectid("…"),
u'u'u'id("…"),
u'u'u'u'id("…")是的采样',
u'u版本':1,
>u'created':datetime.datetime(…,tzinfo=UTC,
u'lonlat':[1.0,3.0],
u'modified':datetime.datetime(…,tzinfo=UTC,
u'name':u'sample'}

{{u'u'sample2',
>u'name':u'sample'''u'sample',
>u'u'''u'u'sample2',
>u'br/>>u'u'id':objectid("…"…'),
>u'u'u'br/>u'("…"),
u"u type":u"geosample",
u"version":2,
u"created":datetime.datetime(…,tzinfo=utc),
u"lon lat":{u"lat":6.0,u"lon":4.0},
u"modified":datetime.datetime(…,tzinfo=utc),
u"name":u"sample2"}

小矩形
(由左下角和右上角坐标指定):printfind(collection,{'lonlat':{'lonlat':{'lonlat':{'$within':{'$box':[[1,2,2],[2,3]]}})

{{'u'sample''u'sample',
u'u'id':objectid('…'),
u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'sample',
>u充足',
u"u version":1,
u"created":datetime.datetime(…,tzinfo=utc),
u"lon lat":[1.0,3.0],
u"modified":datetime.datetime(…,tzinfo=utc),
u"name":u"sample"}

/>>>>printfind(collection,{'lonlat':{'$within':{'$box':[[10,20],[20,30]]}})


tfind(collection,{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{{'center':[[0,0,0,0,4]}}})
{u'u'u'sample',
u'u'u id':objectid("…"),
u'u'u pid':objectid("…"…"),
u'u'pid':objectid("…"…"),
u'pid':objectid("…"…"),
u'u'pid':objectid("…"),
u'u'u'u'u类型:u'ge,
u'lonlat':[1.0、3.0],
u'modified':datetime.datetime(…,tzinfo=utc),
u'name':u'sample'}

>>>gt;printfind(collection,{'lonlat':{'lonlat''{'lon'lonlat':{'lon'lonlat'{'lon'lonlat''''''$center':[[0,0,10]}}}}}}}
{{{u'name''u'sample',
u'0],
u'br/>u'u'u'u'name''''u'u'sample''''sample'''''u'sample'),
u"类型":U'GeoSample,
U'U'GeoSample,
U'created':datetime.datetime(…,tzinfo=UTC),
U'lonlat':[1.0,3.0],
U'modified':datetime.datetime(…,tzinfo=UTC),
U'name':U'Sample'}
{{U'U'Sample2',
>U'Sample':U'Sample':U'Sample'}
{{U'Sample2',
U'U'ID':objectid("…"),
U'PID'u'U'PID',
U'PID'U'U:objectid("…"),
u"类型":u"地理样本",
u"版本":2,
u'c已创建:datetime.datetime(…,tzinfo=utc),
u'lon lat':{u'lat':6.0,u'lon':4.0},
u'modified':datetime.datetime(…,tzinfo=utc),
u'name':u'sample2'}

还要检查lat/lon顺序是否重要:

>;>;printfind(collection,{'lonlat':{'$within':{'$ce":[[1,2,1]}}})
{br/>{u'sample''u'sample',
u'id':objectid("…"),
u'pid':objectid("…"),
u'id':objectid("…"),
u'id':u'geossample',
u'u版本":1,
u'created':datetime.datetime(…,tzinfo=UTC,
u'lonlat u'lonlat':[1.0,3.0,3.0,
u'u'id':objectid("…":objectid("…"…")),

u"修改":datetime.datetime(…,tzinfo=utc),
u'name:u'sample}

>;>printfind(collection,{'lon lat':{'$within':{'$center':[[2,1],1]}})




并使用float检查是否可以存储真实的lon/lat值:

>;data={'name':u'sample','lonlat':{'lon':20.123,'lat':29.123}
>;>sample3=测试。地理样本(数据)
>;>root[u'sample3']=sample3

>;>transaction.commit()

>;>printfind(集合,{'lonlat':{'$在':{'$center':[[25,25],4]}}})

>;printfind(集合,{'lonlat':{{'lonlat':{'lonlat':{'within':{'within':[[25,25,25,10]}}})
{{'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'pid':objectid("…"…"),
'u'u'u'u'u'u'u'id':objectid("…"),
u'u'u'u'u'u'u'u'u'u'u'pid'''':objectid("…"),u'lonlat':{u'lat':29.123,u'l打开:20.123},
u"modified":datetime.datetime(…,tzinfo=utc),
u"name":u"sample"}





>;>;来自m01.mongo import local
>;>;pprint(local.\uu dict\uu)
{}



==
=
geopoint
==


geopoint项可以存储地理位置,并在项中用作提供经纬度和类型的子项。除此之外,地质点还提供了已更改的调度概念,并能够在lon/lat更改时通知父项。该项还为安全查找支持提供
ilocation。MongogeOpointProperty字段属性
负责应用父项和名称,并使用正确的类
工厂。


geopointProperty项支持经度、纬度顺序并保留它们。



condition
----

我们的线程本地缓存是空的,或者如果我们已经从以前的测试中删除了一些垃圾:

>;>;来自m01.mongo.testing import pprint
>;>;来自m01.mongo.testing import renormalizer
>;>;来自m01.mongo.testing import renormalizer
>;>;pprint(local.\uu dict__)
{}



设置
----


>首先导入一些组件:

>;
>;导入日期时间
>;>import事务

>;>import m01.mongo
>;>import m01.mongo.base
>;>import m01.mongo.geo
>;>从m01导入m01.mongo.container
>;>让我们定义一个静态MongoContainer
作为我们的应用程序数据库根项。

>;>Class MongoRoot(m01.mongo.container.MongoContainer):
…"Mongo应用程序根"

…_ id=m01.mongo.getobjectid(0)

…定义初始化(自身):
…通过

…@属性
…def收集(自身):
…返回testing.getrootitems()

…@属性
…def cachekey(self):
…返回"根"

…def load(self,data):
…""负载DA进入右边的Mongo项目。""
…返回测试。地质点样本(数据)

…定义代表(自我):
…返回'<;%s%s>;'%(self.\u class\uu.\u name\uu,self.\u id)



这使我们可以显示生成不同的根项,就像在服务器重新启动时一样。


>;>;def getroot():
…return mongoroot()

这是我们的数据库根项:

>t设置索引:collection=testing.getrootitems()

>;>e可以在lon/lat值列表中
或lon/lat dict中初始化一个地质点:

>;>;数据{'name':u'sample','lonlat':{'lon':1,'lat':3}
>;>;样本=测试。geopointsample(数据)
>;>;样本。lonlat
<;geopoint lon:1.0,lat:3.0>;

>;>data={'name':u'sample','lon lat':[1,3]}
>;>sample=测试。geopointsample(data)
>;>sample.lonlat
<;geopoint lon:1.0,lat:3.0>;

>;>root[u'sample']=示例

>;
让我们检查一下我们在蒙哥的项目:数据集。查找一个({'name''sample''sample'})
>;数据集;重正化器。pprint(数据)
{u'sample''u'sample''u'sample''u'ppint,
u'id''u'u id''objectid("…"),
u'pid''u'pid''u'pid''objectid("…"),
u'u'u-id''''objectid("…"),
u'br/>u'u'u'u-id''''''''u-id'''''''''''''''br/>版本版本:1,
u"created":datetime.datetime(…,tzinfo=utc),
u"lonlat":{u"coordinates":[1.0,3.0],u"type":u"point"},
u"modified":datetime.datetime(…,tzinfo=utc),
u"name":u"sample"}

1.mongo.geo.geopoint({u'lat':4,u'lon':2})
>;>data={'name':u'sample2','lonlat':geo}
>;>sample2=测试。geopointsample(data)
>;>root[u'sample2']=sample2

>;>transaction.commit()
>;>data=collection.f其中一个({'name':'sample2''sample2'})
>>gt>gt>gt>gt;重整化器.pprint(数据)
{u'sample2''u'sample2',
u'id':objectid('…'),
u'id':objectid('…'),
u'pid':objectid('…'),
u'pid':objectid('…'),
u'pid':objectid('…'),
u'pid':objectid('…'),
u'u'u'u'u'id''''''',
u'u'u'u'u信息=UTC),
伦敦t':{u'coordinates':[2.0,4.0],u'type':u'point'},
u'modified':datetime.datetime(…,tzinfo=utc),
u'name':u'sample2'}



":4,'lat':6})
>>>>gt>gt;sample2.lonlat2.lonlat2.lonlat2.lonlat2.lonlat2.lonlat2.lonlat2.lonlat=geo
>
>>
>>>gt;数据=收集。发现一个({'name':'sample2'sample2'})
>>gt>gt>gt;重新规范化r.ppprint(数据)renormalizer.ppprint(数据)
>
{u-name'u'sample2'sample2',
u'br/>u-id':objectid("…"…"…''>u'objectid'>u'objectid'),
u''u pid':objectid("…",
u"type":u"geopointsample",
u"version":2,
u"created":datetime.datetime(…,tzinfo=utc),
u"lonlat":{u"coordinates":[4.0,6.0],u"type":u"point"},
u"modified":datetime.datetime(…,tzinfo=utc),
u"name":u"sample2"}




ind例如,
----

>;>pprint(collection.index_information())
{'{'''{'键':[(''u id',1)],'ns':'m01旺戈测试项目','v':1},
'隆拉特球':{'2dsphereindexversion':2,
'键':[('lonlat','2dsphere')],
'ns':'m01_mongo_testing.items',
'v':1}




search
----


现在请参见搜索地理位置:

>;>def printfind(集合,查询):
…对于collection.find(查询)中的数据:
…renormalizer.pprint(data)


使用地理空间索引,我们可以在另一个点中找到文档:

>;>point={"type":"polygon",
…座标"[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]}
>;查询{"lonlat":{"$within":{"$geometry":点}}
>;printfind(collection,查询)
{{u'sample''u'sample''u'sample',
u'id':objectid("…"),
u'u'sample''u'sample',
u'u'id':objectid("…"),
u'pid':objectid("…"),
u'pid':objectid("…
u"类型":u"geopointsample',
u"版本":1,
u"创建":datetime.datetime(…,tzinfo=utc),
u"lonlat":{u"坐标":[1.0,3.0],u"类型":u"点"},
u"修改":datetime.datetime(…,tzinfo=utc),
u"名称":u"示例"}

其他点:

>
>>gt>gt;point={'type':'point'''''点','坐标':[0,2]}
>>gt;printfind(collection,{'lonlat':{'$near':{'$geometry':point}})

{{'u'u'sample',
u'u'u'u'sample',
u'u'u'u'u'u'u'sample',
u'u'u'u'id':objectid("…"),
u'u'u'id("…"),
u'u'u'u'u型:u'geopointsam",
u'u版本":1,
>u'created':datetime.datetime(…,tzinfo=UTC,
u'lonlat':{u'lonlat':[1.0,3.0,]u'type':u'point'},
>u'modified':datetime.datetime(…,tzinfo=UTC,
>u'name':u'sample'}
>u'sample':u'sample'}
>u'sample',
>u'u'sample':1,
>u'sample':1,

>u'sample':u'sample':1,

u"pid":objectid("…"),
u"type":u"geopointsample",
u"version":2,
u"created":datetime.datetime(…,tzinfo=utc),
u"lonlat":{u"coordinates":[4.0,6.0],u"type":u"point"},
u"modified":datetime.datetime(…,tzinfo=utc),
u"name":u"sample2"}

还可以查询给定矩形中的所有项
(由左下和右上坐标指定):

u"u pid":objectid("…"),
u"type":u"geopointsample",
u"version":1,
u"created":datetime.datetime(…,tzinfo=utc),
u"lonlat":{u"coordinates":[1.0,3.0],u"type":u"point"},
u"modified":datetime.datetime(…,tzinfo=utc),
u"name":u"sample"}

如您所见,如果我们对lon/lat(lat/lon)使用错误的顺序,我们将不会得到值:


>;>printfind(collection,{'lonlat':{'$within':{'$box':[[2,1],[3,2]]}})

ntfind(collection,{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat'${'lon>
>>gt;printfind(collection,{'lonlat'lonlat':{'lonlat'lonlat':[[0,0],4]}}}}}})
{{'u-name''u'sample',
u-id':objectid('…'"…")),
u-id''u-id':objectid('…'),
u-pid':objectid('),
u"类型":u"geopointsample",
u"version":1,
u"created":datetime.datetime(…,tzinfo=utc),
u"lonlat":{u"coordinates":[1.0,3.0],u"type":u"point"},
u"modified":datetime.datetime(…,tzinfo=utc),
u"name":u"sample"}

>;>printfind(collection,{lonlat:{'$within':{'$center':[[0,0,10]}}})
{u'sample'u'sample,
u'id':objectid("…"),
u'pid':objectid("…"),
u'id':objectid("…"),
u'id':u'geopointsample,
u'u版本:1,
u'created''created':datetime.datetime(…,tzinfo=UTC),
u'lonlatu'lonlat':{u'u'co坐标':{'u'u'u'u'co坐标',
u'id':objectid':objectid("…"[1.0,3.0],u"类型":u"点"t'},
u'modified':datetime.datetime(…,tzinfo=utc),
u'name':u'sample'}
{br/>{u'sample2''u'sample2''u'sample2''u'sample2''u'sample2''u'id''u'u'id''objectid("…"),
u'pid''u'pid''objectid("…"),
u'u'id''u'u'u'u'u'geopoi点采样',
u'u'u'u''u'u'u'u'pid'''u'pid''u'pid''pid'''''''''…''u'u'pid''''''''''''''…''u'u'u'id''id'类型:u'point},
u'modified':datetime.datetime(…,tzinfo=utc),
u'name':u'sample2'}


>还要检查lat/lon订单是否重要:printfind(collection,{'lonlat':{'lonlat':{'$center':[[1,2,1]}}}};
{{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'loncenter':[[1,2,1]}}}}}{br/>u'id':objectid("…"),
u'id':objectid("…"),
u'id'…",
u'id("…"),
u'pid"u类型":u"geopointsample",
u"u版本":1,
u"已创建":datetime.datetime(…,tzinfo=utc),
u'lonlat':{u'coordinates':[1.0,3.0],u'type':u'point'},
u'modified':datetime.datetime(…,tzinfo=utc),
u'name':u'sample'}

>>printfind(collection,{'lonlat':{'$within':{'$center':[[2,1],}}}}





>br/>>并检查我们是否可以通过使用浮点值来存储实数lon/lat值:浮点值:

>>>gt;数据={'name':u'sample,'lonlat':{'lon'lon':20.123,'lat':29.123}}
>>;sample3=testing.geopointsample3=sample3=testing.geopointsamplesample(数据)
>>gt>br/>


>>

>>gt>gt>>br/>






>>>()

>;>;printfind(collection,{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat':{'lonlat'{'lonlat':{>
>;gt;printfind(colleclection,{'lonlat':{'lonlat':{'$center':[[25,25,10]}}}}}}})
{{'u{'u name'u'sample3',
>u/>u'id':objectid('…'…'),
u'u{'lonlat u'''''''d("…"),
u"类型":u"geopointsample",
u"版本":1,
u"已创建":datetime.datetime(…,tzinfo=utc),
u"lonlat":{u"坐标":[20.123,29.123],u"类型":u"点"},
u"已修改":datetime.datetime(…,tzinfo=utc),
u"名称":u"示例"}


ClearThreadLocalCache()

正如您所看到的,我们的缓存项已被删除:

>;>;来自M01.mongo import local
>;>;pprint(local.\uu dict\uu)
{}



==
=
批处理
==




MongoMappingBase类用于MongoStorage和MongoContainer可以返回批处理的数据或项以及批处理信息。

注意:此测试在第2级运行,因为它使用的是工作的MongoDB。这是必需的,因为我们喜欢在MongoDB中测试真正的排序和限制函数。



从m01.mongo import local
>;>pprint(local.\uu dict
{}

setup
----


>首先导入一些组件:

>;>;>import transaction
>;>从m01.mongo导入测试



设置
----


现在我们可以向数据库添加MongoStorage。让我们使用一个简单的
dict作为数据库根目录:

>;>;>storage=testing.samplestorage()
>;>root['storage']=storage
>;>transaction.commit()

对于范围(1000)内的i:
…数据={u'title':u'title%i%i,
…u'description':u'description%i'%i,
…u'number':i}
…item=测试。样本存储item(数据)
…_ name_uu=storage.add(item)

>;>transaction.commit()


提交到MongoDB后,Mongo对象和我们的事务数据
管理器引用应在线程本地缓存中消失:

>;,来自M01.mongo import local
>;>pprint(本地的。如您所见,我们的集合包含1000个项:

这是您应该使用的。如果这不适合,因为您需要一个真正的
mongoitem的列表,这将是一个复杂的问题,因为我们可以在本地缓存中删除MongoDB不知道的标记项。


让我们获取批处理信息:

>;storage.getbatchdata()
(<;…光标对象位于…>;,1,40,1000)


如您所见,我们有一个带有mongo数据、开始索引、项目总数和页面计数器的光标。注意,第一页从1(一)开始,而不是从零开始。让我们用不同的值显示另一个示例:

>;>storage.getbatchdata(page=5,size=10)
(<;…cursor object at…>;,5,100,1000)





>gt>gt>gt>gt

(元组(指针))
({''u-name'u'u'u'u'u'u'u'u'u'u'u'u'u'id'…',
''u id':objectid('…'),
''u-pid':无,
''u-id''u-type':'samplestorageitem',
''u-version':1,
'评论':[],
'created':datetime.datetime.datetime(…,tzinfo=utc),tzinfo=utc,


'date日期':无,
是的'description':'description…',
'item':无,
'modified':datetime.datetime(…,tzinfo=utc),
'number':…,
'numbers':[],
'title':'title…'},
{'{''name':'…',
''u id':objectid('…'),
''u-pid':无,
''u-type':'示例torageitem,
"u version":1,
"comments":[],
"created":datetime.datetime(…,tzinfo=utc),
"date":none,
"description":"description…",
"item":none,
"modified":datetime.datetime(…,tzinfo=utc),
"number":…,
"numbers":[],
"标题":"标题…",
{"名称":"…",
"ID":对象ID("…",
"U PID":无,
"U类型":"SampleStorageitem",
"U版本":1,
"注释":[],
"创建":DateTime.DateTime(…,Tzinfo=UTC),
"日期":无,
"说明":"描述…",
"项":无,
"修改":日期时间.datetime(…,tzinfo=utc),
"数字":…,
"数字":[],
"标题":"标题…"})


/>
但是我们可以使用
true作为参数来强制基于limit和skip参数计算结果:


>;>;cursor.count(true)
3


我们可以使用我们的线程本地缓存清理事件处理程序
,它通常注册为endrequestevent订阅服务器:

>;,来自m01.mongo import local
>;>pprint(local.\u u dict\uu)
{u'm01\u mongo\u testing.test…':{added':{},'removed':{}}}

e我们的订户:

>;>M01.mongo导入clearthreadlocache
>;


顺序
----

批处理的一个重要部分是顺序。如您所见,我们可以限制
批处理大小并从序列中获取数据片段。在我们将数据分成一批之前,在MongoDB上对数据进行排序是非常重要的。
让我们根据Ordable数字值和排序顺序(最低值优先)来测试这是否有效。从page=0开始:

>;>cursor,page,page s,total=storage.getbatchdata(page=1,s大小=3,
…sortname='number',sortorder=1)

>;>;cursor
<;pymongo.cursor.cursor object at…>;

>;>;page
1

>;>;pages
334

>;>;total
1000


数值0(零):


>gt>gt>gt>gt>p print(元组(指针))

({u'u'u'u'u'u'u'u'u'u'u id':objectid("…"),
'u-pid':无,
u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'
"日期":无,
u"说明":u"说明0",
"项目":无,
u"修改":datetime.datetime(…,tzinfo=utc),
u"编号":0,
u"编号":[],
u"标题":u"标题0"},
{u"名称":u"…",
u"id":objectid("…",
u pid":非e,
u"类型":u"采样存储项",
u"版本":1,
u"注释":[],
u"创建":datetime.datetime(…,tzinfo=utc),
"日期":无,
u"描述":u"描述1",
"项":无,
u"修改":datetime.datetime(…,tzinfo=utc),
u'number':1,
>u'number':[],
>u'title':u'title 1'},
{u'u'u'u'u'u'u'title 1',

u'u'u id':objectid("…"),
'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'u'number':1,
>u'u'u'number':1,
>u'u'u'u'u'u'u'number':1,
>u'u'u'u'u'u'u'u'u'u'u,
"日期":无,
u"说明":u"说明2",
"项目":无,
u"修改":datetime.datetime(…,tzinfo=utc),
u"数字":2,
u"数字":[],
u"标题":u"标题2"})

>;gt;光标,页,页,总计=存储。GetBatchData(页=2,大小=3,
…sortname'number,sortorder=1)
>>gt>gt>gt;ppprint(tuple(cursor))
({u'u'u'u'u'u'u'…',
u'u id':objectid('…'),
'u pid':none,
u'u'u类型:u'samplestoreageitem,
u'u版本:1,
u'comments':[],
u'created':datetime.datetime(…,tzinfo=utc,tzinfo=utc,
u'u'pid':none,
u'u类型:u'samplestorageitem':u'sam是的),
"日期":无,
u"描述":u"描述3",
"项目":无,
u"修改":datetime.datetime(…,tzinfo=utc),
u"编号":3,
u"编号":[],
u"标题":u"标题3"},
{u"名称":u"…",
u"id":objectid("…",
":无,
u"类型":u"sampleStorageitem",
u"版本":1,
u"注释":[],
u"创建":datetime.datetime(…,tzinfo=utc),
"日期":无,
u"描述":u"描述4",
"项目":无,
u"修改":datetime.datetime(…,tzinfo=utc),
U数:4,
>U数:4,
>U数:4,
>U数:4,

{u名‘‘‘‘‘‘,
U数:ID("…"),
‘‘U PID’:无,
u类型:U数:U数:SampleStorageitem,
U数:1,
>U数:评论":[],
u数:4,
u数:4,
u数:4,
u数:4,
u数:4,
u数:U数:4'title'是的c),
"日期":无,
u"说明":u"说明5",
"项目":无,
u"修改":datetime.datetime(…,tzinfo=utc),
u"编号":5,
u"编号":[],
u"标题":u"标题5"})

让我们看看这批切片。此批中的
项目的编号应为=999。但请注意:

>;>pages
334

>;>cursor,page,total,pages=storage.getBatchData(page=334,size=3,
…sortname'number,sortorder=1)
>>gt>gt>gt;ppprint(tuple(cursor))
({u'u'u'u'u'u'u'…',
u'u id':objectid('…'),
'u pid':none,
u'u'u类型:u'samplestoreageitem,
u'u版本:1,
u'comments':[],
u'created':datetime.datetime(…,tzinfo=utc,tzinfo=utc,
u'u'pid':none,
u'u类型:u'samplestorageitem':u'sam是的),
"日期":无,
u"说明":u"说明999",
"项目":无,
u'modified':datetime.datetime(…,tzinfo=utc),
u'number':999,
u'numbers':[],
u'title':u'title 999'},)




teardown
--


/>再次,清除线程本地缓存:

>;>;clearthreadlocalcache()


/>>;>>导入re
>;>>导入日期时间
>;>>导入bson.tz-util
>;>导入m01.mongo
>;>导入m01.mongo.testing
>;>从m01.mongo.testing导入pprint

er能够规范化文本并生成可比较的输出。您可以使用输入、输出表达式列表来设置renormalizer。如果转储包含日期或其他不太简单的可复制数据的MongoDB数据,则此选项可用。这样的转储结果可以在单元测试
比较输出之前得到规范化。另请参见zope.testing.renormalizing,以获取可用作doctest检查器的相同模式。

>;>;normalizer=m01.mongo.testing.renormalizer([
…(重新编译('[0-9]*[.][0-9]*seconds'),'…秒),
…(重新编译('at x[0-9a-f]+'),'at…'),
…])

>;>;文本="
…<;位于0xB7F14438的对象>;
…在1.234秒内完成。
……
…<;对象对象位于0xb7f14450>;
…在1.234秒内完成。
…""

>;>print normalizer(文本)
<;blankline>;
<;object object at…>;
完成于…秒。

<;对象位于…>;
完成于…秒。
<;blankline>;

现在让我们测试一些与MongoDB相关的内容:

>;>;来自bson.dbref import dbref
>;>;来自bson.min廑u key import minkey
>;>;来自bson.max廑u key import maxkey
>;>;来自bson.objectid import objectid
>>>>来自bson.timestamp import timestamp

>>>oid=m01.mongo.getobjectid(42)
>>>oid
objectid('000000200000000000')

>;data={oid':oid,
…。dbref':dbref("foo",5,"db"),
…'日期:datetime.datetime(2011,5,7,1,12),
…utc":datetime.datetime(2011年5月7日1月12日,tzinfo=bson.tz_util.utc),
…最小值:minkey(),
…max':maxkey(),
…'timestamp:时间戳(4,13),
…。re:重新编译("a*b",re.ignorecase),
…字符串":"字符串",
…"unicode':u'unicode',
…'int:42}


现在让我们漂亮地打印数据:

>;pprint(data)
{date':datetime.datetime(…),
'dbref':dbref('foo',5,'db'),
'int':42,
'max':maxkey(),
'min':minkey(),
'oid':objectid('…'),
're':<;《sre.sre》模式o对象位于…>;,
"string":"string",
"timestamp":时间戳("…",
"unicode":"unicode",
"utc":datetime.datetime(…,tzinfo=utc)}



renormalizer
~en模式:

>;>import m01.mongo.testing
>;>res=m01.mongo.testing.renormalizer(data)
>;>print res
{date':datetime.datetime(…),
'dbref':dbref('foo',5,'db'),
'int':42,
'max':maxkey(),
'min':minkey(),
"oid":objectid("…"),
"re":<;sre.sre_pattern object at…>;,
"string":"string",
"timestamp":时间戳("…",
"unicode":u"unicode",
"utc":日期时间.datetime(…,tzinfo=utc)}


~~~~~

>;>m01.mongo.testing.renormalizer.pprint(data)
{"date":日期时间.datetime(…),
"dbref":dbref('foo',5,'db'),
"int":42,
'max':maxkey(),
'min':minkey(),
'oid':objectid('…'),
're':<;\u sre.sre_pattern object at…>;,
'string':'string',
'timestamp':timestamp('…'),
'unicode':u'unicode',
'utc':datetime.datetime(…,tzinfo=utc)}


utc
--

pymongo库提供自定义的utc实现,包括deepcopy使用的pickle支持。让我们测试这个实现是否有效,并用bson.tz_info.utc替换我们的自定义时区
datetime.datetime(2011,5,7,1,12,tzinfo=utc)


重要信息。



values and items
----


MongoContainers和MongoStorage实现将加载
values and items方法中的所有数据。即使我们已经在线程中缓存了它们。这里有一个优化的方法,如果需要加载大量数据,可以使用它。


mongomappingbase.values的原始实现如下:


def values(self):
在self.dofind(self.collection)中:
尝试:
加载、定位和缓存如果没有缓存
obj=self.doload(data)
除了(keyerror,typeerror):
继续
生成obj
还返回尚未存储在mongodb中的项
对于self中的k、v,cache_added.items():
yield v


如果要阻止加载所有数据,可能只能加载尚未缓存的项的
键和查找数据。这将
减少网络流量,并且看起来像::

def values(self):
_ name_uu=data["uu name_uu"]
如果"uu name_uu"在self中,则删除缓存:
跳过已删除的项
继续
obj=self。加载缓存。获取(uu name_uu)
如果obj为none:
尝试:
可以从mongo加载数据
d=self.dofindone(self.collection,data)
ield obj
还返回尚未存储在mongodb中的项
对于k,v为self。产生v

注意:相同的概念可以用于items方法。

注意:我不建议为大型集合调用键、值或项
a随时都可以。看看我们实现的批处理概念。
getBatchData方法可能是您需要与大型SE一起使用的方法数据的t。



AdvancedConverter
---------


下面的类显示了一个高级实现,它能够转换嵌套数据结构。


通常转换器可以转换属性值。如果属性
值是包含另一个项列表的项列表,则需要使用另一个能够转换此嵌套结构的转换器。但是
正常这是第一级项转换其
值的责任。这就是我们在默认情况下没有实现这个概念的原因。

return house
else:
返回值

类定义如下::



rn car(value)

converter={'myitems':{'house':tohouse,'car':tocar}


class advancedcondverter(object):

converter={}attr name/converter或{u type:converter}
def convert(self,key,value):
"这个convert方法知道如何处理嵌套转换器。""
converter=self.converters.get(key)
如果converter不是none:
如果是instance(converter,dict):
如果是instance(value,(list,tuple)):
res=[]
对于o in value:
如果是实例(o,dict):
u type=o.get(''u type')
如果u type不是none:
converter=converter.get(''u type)
value=converter(o)
res.append(value)
value=res
elif isinstance(value,dict):
u type=o.get(''u type')
如果u type不是none:
converter=converter.get(''u type)
value=converter(value)
else:
value=converter(value)
else:
如果是instance(value,(list,tuple)):
convert list values
value=[converter(d)for d in value]
否则:
转换简单值
value=converter(value)
返回值

拥有能够为您的用例做正确事情的特殊方法。



====
=
=
=
=



3.3.0(2018-02-04)
----


-使用新的p01.env包来设置Pymongo客户端环境--

-错误修复:从mongo客户端测试设置中删除fakemongoconnectionpool

-将mongodb_connect设置为默认值为false,因为客户端设置对测试设置花费的时间太长。如果需要在应用程序启动时进行连接,请将MongoDB\u连接添加到OS环境。





3.2.2(2018-01-29)
----


-错误修复:修复超时毫秒和MongoDB\u吊销列表属性使用


<3.2.1(2018-01-29)
-

-错误修复:将mongodb_server_selection_timeout乘以1000,因为它被用作毫秒




>3.2.0(2018-01-29)
----


-功能:基于环境变量和默认设置实现了pymongo客户端设置。py文件



3.1.0(2017~01-22)
----

-错误修复:如果python对象中的值
为none,请确保我们使用none覆盖现有的mongodb值。以前的版本没有使用"无"覆盖现有值。新实现将使用默认模式值
作为mongodb值,即使默认值为none。注意,这将中断现有的
测试输出。

-bugfix:fix performance test setup,conditional include zodb for performance
测试。支持setup.py中的extras-require。



3.0.0(2015-11-11)
---------

-使用3.0.0作为包版本并反映pymongo>;3.0.0的兼容性。

-功能:更改内部dofind、doinsert和doremove方法,删除safe等旧的

-功能:反映皮蒙戈3.0.0。用close
方法替换disconnect,就像mongoclient那样。

-删除mongoconnectionpool,在代码中用mongoclient替换它们。不需要线程安全连接池,因为pymongo是线程安全的。
在测试代码中也用mongoclient替换mongoconnection。

-从m01.mongofake切换到m01.fake,包括pymongo>;=3.0.0支持

-删除映射基类中的write-concern选项。MongoClient应定义正确的写入问题。




1.0.0(2015-03-17)
----


-改进对象设置上的AttributeRor处理。附加catch valueerror
和zope.interface.invalid并引发attributeerror,其中包含详细属性
和值信息



0.11.1(2014-04-10)
----


-功能:将Mongo客户端最大池大小值从10MB更改为100MB,这反映了PyMongo>中的更改;=2.6.



0.11.0(2013-1-23)
———————————————————————————————————————————————————————————————————————————同时提供一个能够创建此类地质点项目的MongogeoPointProperty,MongogeoPointProperty,MongogeoPointProperty,MongogeoPointProperty,MongogeoPointProperty,MongoPointProperty,MongoPointProperty,MongoPointProperty,MongoPointProperty,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,MongoPoint,Mon/>-功能:实现MongoDateTime架构字段支持时区信息
属性(tzinfo=utc)。



0.10.0(2012-12-16)
----


-从连接切换到MongoClient建议从PyMongo 2.4开始。用写问题选项替换了
safe。默认情况下,pymongo现在将使用安全写入。

-使用mongoclient作为mongoconnectionpool中的工厂。我们没有重命名类
mongoconnectionpool,我们将保持它们的原样。我们也不会重命名imongonconnectionpool接口。

-用
u-m-m-m-u-safe-insert、\u-m-u-safe-update、\u-m-u-safe-remove替换为
u-m-u-insert-u-write-concern、\u-m-u-update-write-concern、\u-m-remove-u-write-concern。
这个新的映射基类选项是一个空的dict,可以用新的write-concern设置替换
。默认的空dict将强制
使用连接中定义的写入问题。



<0.9.0(2012-12-10)
----

-m01.mongofake用于假mongodb,collection and friends


0.8.0(2012-11-18)
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————防止将项目标记为已更改的相同值

-改进排序,支持键或列表作为sortname,如果给定了sortname,则允许跳过sortorder


-添加了manifest.in file



>0.7.0(2012-05-22)
----


-错误修复:fakecollection.remove:使用find查找文档

-通过使用son进行查询筛选和转储方法保留顺序

-实现M01.mongo.dic公司t可以用普通dict实例替换所有bson.son.son





<0.6.2(2012-03-12)
----


-错误修复:遗漏了方法




0.6.1(2012-03-12)
----


-错误修复:在fakemongoconnection中返回selfOD。这让一个
实例的行为类似于原始Pymongo连接类的方法。

doc,该doc总是被忽略。

-bugfix:正确生成UTC中的对象ID。它依赖于gmt+1
(即罗杰的时区)。

-bugfix:允许使用none作为mongodateproperty值

-bugfix:在mongousubitem in it方法中设置父项,如果给定

-implemented作为标记,以便在需要跟踪
changed attrib时查找utes

-在mongoistdata和mongoitemsdata中实现了clear方法,该方法允许
立即删除序列项,而不必从序列中弹出每个项

-改进mongoobject实现,实现了存储mongoobject的父字段名的字段存储在。也可以调整
mongoobjectproperty并支持向后兼容性,方法是应用前面的
存储的"名称"字段(如果未给定)。这个新的字段和名称分隔允许我们使用显式的名称,例如,可以通过遍历器或其他类似容器的实现来遍历MongoObject的ID或自定义名称。这允许获得一个sub
集合,就像在pymongo中一样,它是gridfs概念的一部分。



<0.5.5(2011-10-14)
----



-使用点表示法实现过滤



<0.5.4(2011-09-27)
-


-修复:真正的mongo db接受t将uple作为"find"的"fields"参数。



0.5.3(2011-09-20)
----


-修复最小过滤表达式(albertas)




<0.5.2(2011-09-19)
----

-添加最小过滤表达式(albertas)

-移动创建和mo修改为自己的接口icreatedmodified

-实现简单通用的初始地理位置支持



>0.5.1(2011-09-09)
----


-修复性能测试
-添加数据库名称和集合名称


<0.5.0(2011-08-19)
--——————————————————————————————————————————————————————————————————————

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
swing Java按钮/网格布局   java列出Google日历中的所有事件   java无效:单击API publisher test按钮后连接到后端时出错   带有内部赋值的java While循环导致checkstyle错误   java为什么trimToSize/ensureCapacity方法提供“公共”级访问?   文件输出流的java问题   ListIterator和并发修改异常的java问题   java如何使用两个URL映射   无法识别使用“./../”构造的字符串java相对路径,为什么?   首次写入remotelyclosedsocket不会触发异常,对吗?JAVA   java OneDrive REST API为文件上载提供了400个无效谓词   Java泛型、集合接口和对象类的问题   OpenSSL Java安全提供程序   jmeter java运行jmx禁用操作