索引不及物和传递的n元关系。
zc.relation的Python项目详细描述
关系目录
内容
-
关系目录
-
概述
-
历史记录
-
设置关系目录
-
创建目录
-
添加关系
搜索
使用更复杂的关系
外部双向关系
多方向关系
附加功能
侦听器
清除方法
复制方法
参数
ignoresearchindex
findrelationtokens()
FindValueTokens(索引名)
结论
查看
下一步
标记和联接:zc.relation catalog extended example
使用搜索索引zc relation catalog extended example"id="id66" rel="nofollow">使用搜索索引:zc.关系目录扩展示例
简介
可传递搜索索引
帮助者
优化关系目录使用
更改
-
1.1.post2(2018-06-18)
-
1.1.post1(2018-06-18)
-
1.1(2018-06-15)
-
1.0(2008-04-23)
-
与zc.relationship 1.x index不兼容
-
更改和新功能
概述
关系目录可用于优化不及物性和及物性。
搜索有限预设维度的n元关系。
例如,可以为简单的双向关系编制索引,如employee to
supervisor;主谓宾语的rdf式三元组;以及更复杂的
主谓宾语与上下文和状态的关系。这些
可使用传递行为的变量定义进行搜索。
目录可以在zodb中使用,也可以单独使用。它是一个普通的,相对来说
免政策工具。
它通常被用作更专业和
受约束的工具和api。三个这样的工具是zc.relationship容器,
plone.relations容器和zc.vault。包裹里的文件,
包括这个,请描述其他可能的用途。
历史记录
这是对zc.relationship包的zodb-only部分的重构。
具体来说,zc.relation目录在很大程度上等同于
关系指数。zc.relationship 2.x行中的索引是
几乎完全向后兼容的zc.relation目录包装。
ZC.关系将继续保持,尽管积极的发展
希望进入ZC.关系。
许多想法来自与凯西邓肯的讨论和代码,特雷斯
西弗、肯·曼海默等等。
设置关系目录
在本节中,我们将介绍以下想法。
-
关系是具有索引值的对象。
-
您可以向关系目录添加值索引,以便能够进行搜索。价值观
可以用可调用或接口元素标识到目录。这个
索引值必须作为单个值或
收藏。
-
关系及其值作为标记存储在目录中:唯一
可以解析回原始值的标识符。整数是
最有效的代币,但其他代币也可以正常工作。
-
令牌类型决定所需的btree模块。
-
必须定义自己的标记化和解析标记的函数。这些
函数在关系和每个
它们的价值指数。
-
关系用
索引
索引
我们将使用一个简单的双向关系作为例子。简介
到一个更复杂的rdf样式主谓对象可以稍后找到
在文档中。
创建目录
想象一个从一个值到另一个值的双向关系。假设我们
建立员工与上司之间的关系:员工可以
有A单一主管。在第一个例子中,
雇员和主管是内在的:雇员有一个指针指向
主管和employee对象本身表示关系。
更进一步说,为了简单起见,员工姓名是唯一的,
可用于代表员工。我们可以使用名称作为"标记"。
令牌类似于关系数据库中的主键。令牌是
识别物体的方法。它必须分类可靠,你必须能够写
在给定正确上下文的情况下可靠地解析为对象的可调用函数。在
zope 3、intid(zope.app.intid)和keyreferences(zope.app.keyreference)是
合理代币的好例子。
我们将在下面看到,您提供了一种将对象转换为令牌的方法,并
对象、关系和每个值索引的标记。
它们可以是完全相同的功能,也可以完全不同,具体取决于
您的需要。
对于速度,整数是最好的标记;其次是其他
不可变,如字符串;后跟非持久对象;后跟
持久对象。这个选择还决定了btree模块的选择,如
我们将在下面看到。
这是我们的玩具示例类。再说一次,我们将使用员工
名称作为标记。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
因此,我们需要定义如何将员工转变为他们的代币。我们称之为
标记化一个"转储"函数。相反,将令牌解析为
对象称为"加载"。
转储关系和值的函数会得到几个参数。第一
参数是要标记化的对象。其次,因为有时候
提供上下文,就是目录。最后一个参数是
为给定搜索共享。字典可以被忽略,或者用作缓存
用于优化(例如,保存您查找的实用程序)。
在这个例子中,我们的函数很简单:我们说令牌
员工姓名。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
如果持久地存储关系目录(例如,在zodb中),请注意
您提供的可调用函数必须是可选择的——模块级函数,
例如。
我们还需要一种方法将代币转换为员工,或"加载"。
"load"函数获取要解析的令牌;目录
上下文;和dict缓存,用于优化后续调用。
您可能已经注意到我们的
员工中有一个映射
在
employees
global dict中要反对的名称的
类定义)。我们将使用它来解析令牌。
< Buff行情>
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
现在我们知道的足够多了,可以开始目录了。我们将实例化它
通过指定如何标记关系,以及什么样的btree模块
应该用来存放代币。
你如何选择btree模块?
-
如果令牌是32位整数,请选择
btrees.family32.ii
,
btrees.family32.if
或
btrees.family32.io
-
如果令牌是64位整数,请选择
btrees.family64.ii
,
btrees.family64.if
或
btrees.family64.io
-
如果它们是其他的,请选择btrees.family32.oi,
btrees.family64.oi
或
btrees.family32.oo
(或
btrees.family64.oo
–它们是相同的。
在这些规则中,选择有点武断,除非您计划合并
这些结果与使用特定btree的另一个源的结果相同
模块。btree set操作只能在同一个模块中工作,因此必须
将模块与模块匹配。目录默认为if树,因为
标准的zope目录使用。这是最合理的选择
如果您的令牌实际上与
zope目录,您需要执行一些设置操作。
在本例中,我们的标记是字符串,因此我们需要oo或oi变体。我们会
丘se btrees.family32.oi,任意。
< Buff行情>
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
< COL/> < COL/>
<正文>
< >
<表>
[1]
目录提供了iCalog。
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
< COL/> < COL/>
<正文>
< >
<表>
看!关系目录!我们做不到
不过,到目前为止,我们已经用它进行了大量的搜索,因为目录中没有
索引:
在本例中,关系本身表示雇员,因此我们不需要
单独编制索引。
但我们需要一种方法告诉目录如何找到
关系,主管。可以使用属性将其指定给目录
或从zope.interface接口指定的方法,或使用可调用的方法。
我们暂时用一个可呼叫的。可调用的将接收索引关系
以及上下文目录。
< Buff行情>
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
我们还需要指定如何标记(转储和加载)这些值。在
在这种情况下,我们可以使用与关系本身相同的函数。
但是,请注意,我们可以指定完全不同的转储和
为每个"值索引"或关系元素加载。
我们还可以指定调用索引的名称,但它将默认为
函数(或接口元素)的
现在就给我们。
现在我们可以添加"主管"值索引。
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
现在我们有了一个索引。
[2]
zc.relationship索引的旧实例,在最新的
版本子类zc.relation catalog,用于在
内部数据结构。我们在这里指定它,以便
将dict转换为oobtree可以运行。
>>> catalog._attrs = dict(catalog._attrs)
< COL/> < COL/>
<正文>
< >
<表>
添加关系
现在让我们创造一些员工。除了一个以外,其他人都有主管。
如果您回忆起我们的玩具employee类,则
构造函数是雇员名称(因此也是标记),并且
可选的第二个参数是主管。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
4
这是层次结构图。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
5
让我们使用
索引
方法告诉目录有关关系的信息。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
6
我们现在已经创建了关系目录并向其中添加了关系。我们准备好了
搜索!
搜索
在本节中,我们将介绍以下想法。
-
对关系目录的查询由dict组成。
-
查询键是要搜索的索引的名称,或者
精确关系的特例,常数
-
查询值是要匹配的结果的标记;或者
无
,
指示将
none
作为值(或空集合)的关系,
如果是倍数)。搜索值可以使用
zc.relation.catalog.any(args)或
zc.relation.catalog.any(args)
none)结果以匹配给定的密钥。
-
索引有多种方法可帮助您使用标记。
tokenizequery
通常是最常用的,尽管其他可用。
-
要查找与查询匹配的关系,请使用
findRelations
或
findrelationtokens
-
要查找与查询匹配的值,请使用
find values
或
findvalues
-
您可以使用查询工厂进行传递性搜索。这个
zc.relation.queryfactory.transportingtransitive
是一个很好的常见情况
允许您在层次结构中上下移动的工厂。查询工厂可以是
作为参数作为
queryfactory
传递给搜索方法,或
作为默认行为安装,使用
addDefaultQueryFactory
-
要查找查询的关联方式,请使用
findRelationChains
或
FindRelationtokenchains
-
要确定查询是否相关,请使用
canfind
-
循环传递关系被处理以防止无限循环。他们
在
findrelationchains
和
findrelationtokenchains
中用
a
zc.relation.interfaces.icircularrelationpath
标记接口。
-
搜索方法共享以下参数:
-
最大深度
,限制搜索的传递深度;
-
过滤,允许代码过滤可传递路径;
-
targetquery
,允许查询根据
终点的;
-
targetfilter
,允许代码根据
端点;和
-
上述queryfactory
。
-
您可以设置搜索索引以加速特定的可传递搜索。
查询、
查找关系和特殊查询值
那么谁为爱丽丝工作呢?这意味着我们想要得到关系
员工-由Alice的主管担任。
目录问题的核心是查询。拼写查询
作为字典。主要的意思是字典里的键
指定索引名称,值指定约束。
查询中的值总是用标记表示的。目录中有
好几个帮手来减轻这件事的负担,但现在让我们
我们的代币易于理解的优势。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
7
艾丽斯是贝蒂和查克的直接上司。
如果你想问"谁不向任何人报告?""那么你想
找一个没有主管的关系。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
8
爱丽丝是唯一一个不向任何人报告的雇员。
如果你想问"谁向黛安或查克报告?""然后你用
zc.relation
any
类或
any
函数传递多个值。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
9
弗兰克、盖林和豪伊都向黛安娜或查克汇报。
[4]
[3]
添加值索引可以生成多个
例外情况。
您必须同时提供转储和加载,或者两者都不提供。
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
在这个例子中,即使我们修复了它,我们也会得到一个错误,因为我们已经
已为主管功能编制索引。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
0
您也不能在同一名称下添加其他函数。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
1
最后,如果函数没有名称
提供一个,您不能添加索引。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
2
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
3
< COL/> < COL/>
<正文>
< >
<表>
查找值
和
关系
查询键
那么,我们如何找到谁是员工的主管呢?好吧,在这种情况下,
看看员工的属性!如果可以使用
通常会在ZODB中获胜。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
1
同样,正如我们在第一个例子开始时提到的,知识
对于员工实例来说,是"固有"的。它是
有可能,甚至很容易,问目录这种问题,但是
目录语法更适合于"外部"关系,例如
从主管到员工:两者之间的联系
主管对象及其员工与主管无关,因此
你可能想要一个目录来找到它!
但是,我们将非常简要地探讨语法,因为它引入了
一对重要的搜索方法,因为它是一块垫脚石
第一次传递搜索。
那么,关系目录,谁是豪伊的主管?
要问这个问题,我们需要从关系中获取索引值:
查找值
。在最简单的形式中,参数是
所需的值,以及一个查询,以查找具有所需的
值:
询问呢?上面,我们注意到查询中的键是
要搜索的索引。但是,在这种情况下,我们不想搜索
与往常一样,更多用于匹配关系的索引,但实际上指定了一个关系:
Howie .
我们没有值索引名称:我们正在查找关系。查询
那么,键应该是常数zc.relation.relation
。为我们的当前
例如,这意味着查询是
{zc.relation.relation:'howie'}
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
2
恭喜,你刚刚发现
写"howie.supervisor"的方式效率低下!
[5]
[4]
任何
都可以比较。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
0
< COL/> < COL/>
<正文>
< >
<表>
[5]
这里的令牌结果是相同的。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
3
当我们在下面的脚注中,我会提到你可以
搜索尚未建立索引的关系。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
4
< COL/> < COL/>
<正文>
< >
<表>
更有用的是,您可以使用其他查询键和
关系。这问,"贝蒂,爱丽丝,弗兰克,谁是
由爱丽丝监督?"
"
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
6
只有贝蒂是。
代币
如上所述,目录提供了几个使用令牌的助手。
最常用的是tokenizequery,它接受一个带有对象的查询
值并使用为注册的"dump"函数将其转换为令牌
关系和索引值。以下是一些
我们在上面遇到的问题。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
7
(如果你想知道最后一个结果中的
无
,是的,
zc.relation.relation
只是
none
的可读性糖。
所以,这里是一个使用
tokenizequery
的实际搜索。我们将为
catalog.tokenizequery
只是为了把事情缩短一点。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
8
目录总是有并行搜索方法,一种用于查找对象的方法,如
如上所示,其中一个用于查找令牌(唯一的异常是
canfind
,
如下所述)。查找标记可以更有效,特别是如果
关系目录的结果只是查找路径的一步
你想要的结果。但对于某些常见情况,查找对象更简单。
下面是上面一些查询的快速示例,获取标记而不是
对象。
您还可以使用关键字参数在
tokenizequery
中拼写查询。这个
如果您的键是
zc.relation.relation
,则不会起作用,否则它可以
提高可读性。下面我们也会看到一些例子。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
9
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
0
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
1
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
2
目录提供了其他几种仅用于处理令牌的方法。
-
resolvequery
:与tokenizequaly的倒数,转换
托克尼zedquery到带有对象的查询。
-
tokenizevalues
:返回给定
索引名。
-
resolveValueTokens
:返回
给定索引名。
-
标记化
:返回给定关系的标记。
-
ResolveRelationToken
:返回给定令牌的关系。
-
标记化
:返回给定关系的一个iterable标记。
-
ResolveRelationTokens
:返回令牌的一个Iterable关系
给定。
这些方法使用较少,并在
这个包裹。
传递式搜索、查询工厂和最大深度
所以,我们看到了很多一级的,不及物的搜索。怎么样
传递搜索?好吧,你得告诉目录怎么走这棵树。
在这种简单(非常常见)的情况下,
zc.relation.queryfactory.transportingtransitive
将起作用。
可传递查询工厂只是目录用来调用的
问"我有这个问题,这是我找到的结果。我应该
可传递地再跨出一步,那么下一步应该搜索什么查询?"
写工厂比我们现在想说的要复杂得多,
但是使用transportingtransitionvequeryfactory很容易。你只要告诉我
它应该转换两个查询名,以便在
方向。
例如,这里我们只想告诉工厂把这两个键调换一下
我们使用了,
zc.relation.relation
和"supervisor"。我们建个工厂吧,
在查询中使用它进行几个可传递的搜索,然后,如果需要,
您可以通过阅读脚注来了解正在发生的事情。
这是工厂。
< Buff行情>
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
3
现在,
工厂
只是一个可调用的。让它来帮助回答几个问题
问题。
Howie所有的主管都是过渡性的(这在
图)
< Buff行情>
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
4
贝蒂所监督的人都是谁,广度优先(这个
在图表中往下看?
< Buff行情>
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
5
是的,看起来不错。那是怎么做到的?如果你在乎,读这个
脚注。
[13]
这个可传递的工厂实际上是唯一一个
需要这个特定的目录,所以连接它可能是安全的
作为违约。可以添加多个查询工厂以匹配不同的
使用
addDefaultQueryFactory进行查询
< Buff行情>
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
6
现在默认情况下,所有搜索都是可传递的。
< Buff行情>
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
7
我们可以使用
maxdepth
[7]
[6]
如果您使用
findValues
或
findValues令牌
如果试图指定一个未编入索引的值名,则会出现一个valueerror。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
5
< COL/> < COL/>
<正文>
< >
<表>
[7]
使用a
maxdepth进行搜索
不
queryfactory
引发错误。
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
8
>>> def loadEmployees(token, catalog, cache):
... return employees[token]
...
9
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
0
< COL/> < COL/>
<正文>
< >
<表>
我们将介绍一些其他可用的搜索
本文档和其他文档中稍后的参数。这很重要
注意
所有搜索方法都与
``查找关系``
。
findValues
和
findValues标记
只添加
指定所需值的初始参数。
我们看了两种搜索方法目前为止的ods:find值
findRelations
方法帮助您询问相关的内容。但是如果你
想知道事物是如何传递相关的吗?
查找关联链
和
目标查询
另一种搜索方法,findrelationchains,可以帮助您发现
事物之间存在传递关系。
方法名为"查找关系链"。但什么是"关系"
"链"?在这个api中,它是关系的传递路径。为了
例如,豪伊的指挥系统是什么?
查找关联链
将返回每个唯一路径。
< Buff行情>
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
3
仔细看看结果。注意,结果是
元组。每个元组是一个唯一的链,它可能是
后继链条。在这种情况下,最后一个链是最长的
最全面。
如果我们想看看爱丽丝的路怎么办?那就是一个
为每个受监督的员工提供链,因为它显示了所有可能的路径。
< Buff行情>
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
4
这就是爱丽丝的所有道路,所有的锁链。我们把结果分类,
但通常情况下,它们是宽度优先的。
但是如果我们只想找到从一个查询结果到
另一个查询结果——比如,我们想知道爱丽丝的命令链
至于豪伊?然后我们可以指定一个
targetquery
来指定
所需终点的特征。
< Buff行情>
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
5
所以,贝蒂监督黛安,黛安监督豪伊。
注意
targetquery
现在将
maxdepth
加入到我们的共享集合中
搜索我们介绍的参数。
过滤器
和
目标过滤器
我们现在可以快速查看两个共享搜索参数中的最后一个:
过滤器
和
目标过滤器
。这两个相似之处在于它们都是
在基于
不管你能编什么逻辑。它们的不同之处在于
过滤器进一步停止
从关系进行传递式搜索,而
targetfilter
仅省略
给定结果,但允许进一步搜索。就像targetquery,然后,
当您想指定路径的另一端时,targetfilter
很好。
例如,假设我们只想让女性员工返回。
< Buff行情>
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
6
以下是所有由Alice过渡性地监督的女性员工,使用
目标滤波器
< Buff行情>
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
7
以下是查克监督的所有女员工。
< Buff行情>
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
8
作为过滤器使用的相同方法只会直接返回雌性
由其他女性监督-在这种情况下,不是Galyn。
< Buff行情>
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
9
它们可以相互结合,也可以与其他搜索相结合
参数
[9]
[8]
最大深度
必须是无或正整数,或者
否则您将得到一个值错误。
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
1
>>> import zc.relation.catalog
>>> import BTrees
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
2
< COL/> < COL/>
<正文>
例如:
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
0
< >
<表>
搜索索引
在不设置任何额外索引的情况下,
findRelations
和findValues方法本质上依赖于
对
findrelationchains
的蛮力搜索。结果是难以接受的
是逐渐计算出来的。例如,让我们重复这个问题
"贝蒂监督谁?"。注意
res
首先填充一个列表
有三个成员,但不会填充第二个列表。这个
迭代器已用尽。
< Buff行情>
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
1
在许多情况下,这种方法的强大威力是足够的,但是
有时速度为搜索搜索至关重要。在这种情况下,你可以
添加"搜索索引"。搜索索引加快了
通过索引结果进行更精确的搜索。搜索索引可以
影响
findRelations中带有
queryfactory
的搜索结果,
findValues
和即将推出的
影响
findrelationchains
relation包目前包含两种搜索索引,一种是
索引可传递成员在层次结构中的搜索和一个不可传递成员的搜索
此包中tokens.rst中探索的搜索,可以优化频繁
对复杂查询的搜索或可以有效地更改
不及物搜索。其他搜索索引实现和方法可能是
以后添加。
下面是一个非常简单的例子,为transitive添加一个搜索索引
上面显示的指定"主管"的搜索。
< Buff行情>
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
2
zc.relation.relation
描述了如何沿着链返回。搜索
在searchindex.rst中对索引进行了合理的详细说明。
现在我们已经添加了索引,我们可以再次搜索。结果是这个
时间已经计算好了,所以,至少当你要求代币时,它
可重复。
< Buff行情>
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
3
请注意,当使用索引时,宽度优先排序将丢失
[10]
< COL/> < COL/>
<正文>
< >
<表>
传递循环(以及更新和删除关系)
可传递搜索和提供的搜索索引可以处理
周期。在当前示例中,周期的可能性比其他一些示例小,
但我们可以把这个案子再延伸一点:想象一个"伪装的国王"
高层的人在下级工作。也许是爱丽丝
为赞恩工作,为贝蒂工作,为爱丽丝工作。人工的,
但很容易画出来:
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
7
也易于创建。
< Buff行情>
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
8
现在我们有一个循环。当然,我们还没有告诉目录。
索引
可用于重新索引alice和index zane。
< Buff行情>
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
9
现在,如果我们问谁为贝蒂工作,我们就得到整棵树。(我们会问
对于令牌,只需查看较小的结果即可。)
[11]
[10]
我们在本文档中看到的场景显示了一个案例
其中搜索索引中的特殊逻辑需要寻址更新。
例如,如果我们将Howie从Diane移走
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
4
致Galyn
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
5
然后,新位置和旧位置的搜索索引都是正确的。
>>> from zope.interface.verify import verifyObject
>>> import zc.relation.interfaces
>>> verifyObject(zc.relation.interfaces.ICatalog, catalog)
True
6
< COL/> < COL/>
<正文>
< >
<表>
如果我们要找弗兰克的主管,包括贝蒂。
< Buff行情>
>>> catalog._attrs = dict(catalog._attrs)
3
findRelationChains返回的路径用特殊接口标记,
以及特殊元数据,以显示链。
< Buff行情>
>>> catalog._attrs = dict(catalog._attrs)
4
这是最后一条链:
< Buff行情>
>>> catalog._attrs = dict(catalog._attrs)
5
链的"cycled"属性具有创建循环的查询列表。
如果运行一个或多个查询,您将看到循环将
重新启动–路径将开始重叠的位置。有时是质疑
结果将包括多个循环,以及一些非循环的路径。
在本例中,只有一个循环查询,结果是
循环关系。
< Buff行情>
>>> catalog._attrs = dict(catalog._attrs)
6
>>> catalog._attrs = dict(catalog._attrs)
7
消除这种疯狂"id="id13" rel="nofollow">[12],我们可以取消zane的索引,然后更改
重新索引爱丽丝。
[11]
对贝蒂、爱丽丝和赞恩的查询结果都是
同样的。
>>> catalog._attrs = dict(catalog._attrs)
0
循环不会污染循环外的索引。
>>> catalog._attrs = dict(catalog._attrs)
1
>>> catalog._attrs = dict(catalog._attrs)
2
< COL/> < COL/>
<正文>
< >
<表>
可以找到
我们到了最后一个搜索方法:
canfind
。我们得到了价值观
关系,但是如果你只是想知道
有联系吗?例如,爱丽丝是豪伊的主管吗?是
扔出?要回答这些问题,可以使用
canfind
方法
与
targetquery
搜索参数结合。
canfind方法的参数与findRelations相同。然而,
它只返回一个关于搜索是否有任何结果的布尔值。这个
是一种方便,还允许进行一些额外的优化。
贝蒂监督谁吗?
< Buff行情>
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
4
豪伊呢?
< Buff行情>
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
5
赞恩(不再是雇员)呢?
< Buff行情>
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
6
如果我们想知道艾丽斯或查克是否监督豪伊
路径上两点的特征。问一个关于另一个的问题
在路径末尾,使用
targetquery
爱丽丝是豪伊的主管吗?
< Buff行情>
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
7
查克是豪伊的主管吗?
< Buff行情>
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
8
Howie Alice是他的雇员吗?
< Buff行情>
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
9
豪伊·查克是他的雇员吗?
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
0
(注意,如果您的关系描述了一个层次结构,则向上搜索层次结构是
通常比向下搜索更有效,所以第二对问题是
在这种情况下,通常比第一种更好。)
使用更复杂的关系
到目前为止,我们的示例使用了一个简单的关系,其中索引对象
是关系的一端,对象上的索引值是另一端。
这个示例让我们查看了所有基本的zc.relation目录
功能。
不过,正如引言中提到的,目录支持
为更复杂的关系而设计。本节将快速检查
很少有其他用途的例子。
在本节中,我们将看到上面提到的一些想法的例子,但不是
但已演示。
-
我们可以使用接口属性(values或callables)来定义值
索引。
-
使用接口属性将导致尝试调整关系,如果
尚未提供接口。
-
在定义值索引时,我们可以使用
multiple
参数来指示
索引值是一个集合。
-
在定义值索引时,我们可以使用
name
参数来指定
要在查询中使用的名称,而不是依赖于接口的名称
属性或可调用。
-
在实例化catalog中的
family
参数允许您更改
关系和值索引的默认btree系列
btrees.family32.if
到
btrees.family64.if
外部双向关系
我们当前故事的一个简单变化是:如果索引关系
在另外两个物体之间——也就是说,如果关系是外在的
两个参与者?
假设我们有亲生关系。我们想要一个
"人"和"父母"关系。我们将为
iparentage
因此我们可以看到如何使用接口定义值索引
作品
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
1
现在我们将定义转储程序和加载程序,然后定义目录。通知THAT
我们依赖一种模式:在加载之前必须调用转储。
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
2
现在我们有一个完整的目录。让我们添加一些关系。
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
3
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
4
这是我们的一个层次结构图。
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
5
现在,我们可以索引这些关系,并提出一些问题。
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
6
多方向关系
上一个例子很快展示了如何为
外在的双向关系。相同的模式可以扩展为n路
关系。例如,考虑一个四向关系
主谓宾语[在上下文中]。例如,我们可以
想说"(乔,)在街角的商店里卖(甜甜圈,咖啡),"(乔,)"
是主语的集合,"sells"是谓语,"(甜甜圈,咖啡)"
是对象的集合,"corner_store"是可选上下文。
对于最后一个例子,我们将集成两个我们还没有看到的组件
以前的版本:zodb和改编版。
我们的示例zodb方法使用oid作为令牌。这可能在一些
如果您永远不支持多个数据库,并且不需要
抽象层,以便不同的对象可以具有相同的标识符。
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
7
(使用zope.component时,
\u conform\uuu
通常是不必要的;
但是,此包不依赖于zope.component。)
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
8
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
9
如前所述,
dumppersistent
和
loadpersistent
有点像玩具
上面。另外,虽然我们的谓词将存储为字符串,但是一些程序员
在这种情况下,可能更喜欢使用转储来验证字符串是否
以某种方式显式注册,以防止输入错误。显然,我们不是
为我们的例子而烦恼。
我们制造一些物体,然后我们与这些物体建立一些关系
为它们编制索引。
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
0
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
1
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
2
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
3
现在我们可以问一个简单的问题。他们在哪里卖甜甜圈?
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
4
希望这些示例能为您提供有关如何使用此工具的进一步想法。
附加功能
本节介绍外围设备功能。我们将学习以下内容。
-
侦听器可以在目录中注册。当一个亲戚
添加、修改或删除;清除并复制目录时
(见下文)。
-
clear方法清除目录中的关系。
-
copy方法通过复制内部目录来复制当前目录
数据结构,而不是重新索引关系,它可以是
重大优化机会。这将复制值索引并搜索
索引;并给侦听器一个机会来指定
应该包含在新副本中。
-
五种相关搜索方法的ignoresearchindex参数
使搜索忽略搜索索引,即使有适当的
一个,
-
findRelationTokens()
(不带参数)返回所有
目录中的关系标记。
-
findValueTokens(index_name)
(其中"index_name"应替换为
索引名)返回目录中所有值标记的btree集
给定的索引名。
听众
当目录发生更改时,可能会有多种潜在的客户端需要得到警报。
zc.relation不依赖于zope.event,因此可以注册侦听器
各种变化。让我们做一个快速的演示监听器。
加法
和
removals
参数是{value name:iterable of added or的字典
远离的值标记}。
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
5
监听器可以多次安装。
侦听器可以作为持久弱引用添加,因此,如果它们是
在其他地方删除后,zodb包将不考虑目录中的引用
防止垃圾收集。
我们将把其中一个演示监听器作为
正常引用,默认行为。然后我们将展示一些示例消息
发送到演示侦听器。
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
6
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
7
这些示例中没有显示的两个方法是
sourcecleared
和
已复制源代码
。我们很快就会看到下面的内容。
清除方法
clear方法只对目录中的所有关系进行索引。安装
侦听器已调用
sourcecleared
。
< Buff行情>
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
8
>>> catalog.addValueIndex(supervisor, dumpEmployees, None,
... btree=BTrees.family32.OI, name='supervisor2')
Traceback (most recent call last):
...
ValueError: either both of 'dump' and 'load' must be None, or neither
9
α
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
00
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
01
复制方法
有时可能需要复制关系目录。一种方法是
若要创建新目录,请将其设置为当前目录,然后重新编制索引
同样的关系。这对程序员来说是不必要的慢,而且
计算机。copy方法用相同的
通过复制内部数据结构建立索引关系。
搜索索引被请求为新的
catalog;并且监听器有机会根据需要对新的
复制,包括安装它们自己和/或它们选择的另一个对象
作为听众。
让我们制作一个包含搜索索引和侦听器的填充索引的副本。
注意,在我们的侦听器中,
sourcecopied
将自己作为侦听器添加到
新副本。这是在复制过程的最后完成的。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
02
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
03
现在,该副本拥有自己的内部数据结构和
搜索索引。例如,让我们修改关系并将新关系添加到
复制.< /P>
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
04
原始目录未被修改。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
05
参数
ignoresearchindex
参数
可以使用搜索索引的五种方法,
findValue
,
findValueTokens
,
findRelations
,
findRelationTokens
,以及
可以显式地请求canfind忽略任何相关的搜索索引
使用
ignoresearchindex
参数。
我们可以通过与令牌相关的方法很容易地看到这一点:搜索索引结果
将是一个btree集合,而如果没有搜索索引,则结果将是
发电机。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
06
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
07
我们可以看到其他方法接受这个参数,但是结果看起来
与往常一样。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
08
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
09
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
10
findrelationtokens()
如果在没有任何参数的情况下调用findrelationtokens,您将得到
目录中所有关系标记的树集。这对测试很方便
以及目录的高级使用。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
11
FindValueTokens(索引名)
如果只使用索引名调用findValueTokens,将得到btree
索引中该值的所有标记的结构。这很方便
测试和目录的高级使用。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
12
结论
回顾
这就结束了我们的介绍我举个例子。让我们回顾一下
然后看看你可以从这里走到哪里。
关系是具有索引值的对象。
关系目录索引关系。这种关系可以是单向的,
双向、三向或N向,只要告诉目录为
不同的值。
创建目录:
< Buff行情>
关系及其值作为标记存储在目录中:唯一
可以解析回原始值的标识符。整数是
最有效的代币,但其他代币也可以正常工作。
令牌类型决定所需的btree模块。
< Buff行情>
-
如果令牌是32位整数,请选择
btrees.family32.ii
,
btrees.family32.if
或
btrees.family32.io
-
如果令牌是64位整数,请选择
btrees.family64.ii
,
btrees.family64.if
或
btrees.family64.io
-
如果它们是其他的,请选择btrees.family32.oi,
btrees.family64.oi
或
btrees.family32.oo
(或
btrees.family64.oo–它们是相同的。
在这些规则中,选择有些武断,除非您计划
将这些结果与使用
特定的btree模块。btree set操作只在同一个
模块,因此您必须将模块与模块匹配。
在实例化catalog中的
family
参数允许您更改
关系和值索引的默认btree系列
btrees.family32.if
到
btrees.family64.if
必须定义自己的标记化和解析标记的函数。
这些函数在关系和
它们的每个值索引。
您可以向关系目录添加值索引,以便能够进行搜索。价值观
可通过可调用项或接口元素标识到目录。
< Buff行情>
-
使用接口属性将导致尝试调整
如果尚未提供接口,则为关系。
-
在将值索引定义为
指示索引值是集合。默认为
错误。
-
在将值索引定义为
指定要在查询中使用的名称,而不是依赖于
接口属性或可调用的名称。
您可以设置搜索索引来加速特定的搜索,通常
可传递。
侦听器可以在目录中注册。当
关系被添加、修改或删除;当目录被清除时
并复制。
目录管理:
< Buff行情>
-
关系用索引(关系)索引,并从
目录中有
未索引(关系)
。
索引文档(关系令牌,
关系)
和
取消索引文档(关系令牌)
也可以工作。
-
clear方法清除目录中的关系。
-
copy方法通过复制来复制当前目录
内部数据结构,而不是重新索引关系,这可以
成为一个重要的优化机会。这将复制值索引和
搜索索引;并使侦听器有机会指定
任何内容,都应包含在新副本中。
搜索目录:
< Buff行情>
对关系目录的查询由dict组成。
查询键是要搜索的索引的名称,或者
精确关系的特殊情况,即
zc.relation.relation
常数。
查询值是要匹配的结果的标记;或者
无
,表示将
无
作为值(或空)的关系
集合(如果是倍数)。搜索值可以使用
zc.关系catlog.any(args)
或
zc.relation.catalog.any(args)
到
指定多个(non-
none
)结果以匹配给定的密钥。
索引有多种方法可帮助您使用标记。
tokenizequery
通常是最常用的,尽管其他的是
可用。
要查找与查询匹配的关系,请使用
findRelations
或
FindRelationtokens
。调用不带任何
参数返回目录中所有关系标记的树集。
要查找与查询匹配的值,请使用
findValues
或
findValueTokens
。仅使用名称调用findValueTokens
返回目录中所有令牌的btree集
价值指数。
您可以使用查询工厂进行传递性搜索。这个
zc.relation.queryfactory.transportingtransitive
是一个很好的常见情况
允许您在层次结构中上下移动的工厂。查询工厂可以
作为搜索方法的参数作为queryfactory传入,或
作为默认行为安装,使用
addDefaultQueryFactory
要查找查询的关联方式,请使用
findRelationChains
或
FindRelationtokenchains
要确定查询是否相关,请使用
canfind
循环传递关系被处理以防止无限循环。他们
在
findrelationchains
和
findrelationtokenchains
中确定
带有一个
zc.relation.interfaces.icircularrelationpath
标记接口。
搜索方法共享以下参数:
-
最大深度
,限制搜索的传递深度;
-
过滤,允许代码过滤可传递路径;
-
targetquery
,允许查询筛选
端点的基础;
-
targetfilter
,允许代码根据
终点;和
-
上述queryfactory
。
此外,
findRelations
的
ignoresearchindex
参数,
FindRelationTokens
,
FindValues
,
FindValues标记
,以及
canfind导致搜索忽略搜索索引,即使存在
一个合适的。
下一步
如果你想读更多的书,接下来的步骤取决于你喜欢怎样学习。在这里
是zc.relation包中的一些其他文档。
<表>
< COL/>
< COL/>
<正文>
< >
<表>
最后,真正的死难者也可能对时间感兴趣
目录,其中包含用于测试假设和学习的脚本。
[12]
如果你想,看看当你去
其他方式:
>>> catalog._attrs = dict(catalog._attrs)
8
>>> catalog._attrs = dict(catalog._attrs)
9
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
0
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
1
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
2
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
3
优化。rst:
优化关系目录使用的最佳实践。
搜索索引。rst:
查询工厂和搜索索引:从基础到细节。
令牌。rst:
本文档探索令牌的详细信息。全神的辣椒
爱情信物,至少如果上帝的奇伦在写非玩具应用程序
使用zc.relation。它包括对令牌助手的讨论
目录提供了如何使用zope.app.intid-like注册表
关系,如何使用令牌合理地"连接"查询结果
以及如何索引连接。这也是不必要的
因为所用的例子,令人心驰神往。
接口。py:
螺母和螺栓的合同。
< COL/> < COL/>
<正文>
< >
<表>
标记和联接:zc.关系目录扩展示例
介绍和设置
本文档假设您已经阅读了介绍性的readme.rst并希望
以身作则。在它中,我们将探索
一组复杂的关系,展示了
使用代币。特别是,我们将研究连接,它将
也让我们有机会更深入地了解查询工厂和
搜索索引,并引入侦听器的思想。它无法解释
自述文件中已经提到的基础知识。
假设我们正在为系统中的安全断言编制索引。在这
系统中,用户可能在组织中具有角色。各组织
可能有多个子组织,也可能只有一个父组织
组织。在父组织中具有角色的用户将具有
在所有传递连接的子关系中扮演相同的角色。
我们有两种关系。一种关系将模型
组织的等级制度。我们用一个内在的关系
组织对孩子的影响:这反映了一个事实
组织选择并由他们的孩子组成;孩子选择
不要选择父母。
另一个关系将为(单个)用户具有的(多个)角色建模
在一个(单一)组织中。这种关系完全是外在的。
我们可以创建两个目录,每种类型一个。或者我们可以把它们
都在同一个目录中。最初,我们将使用单个目录
我们的例子。那么,这个目录将为
关系的异构集合。
让我们用接口定义这两种关系。我们将包括一个
访问器,getorganization,主要用于显示如何处理方法。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
13
现在我们可以创建一些类。在自述示例中,设置有点
玩具的这次我们会更实际一点。我们也会期待
在zodb中操作,有根和事务。
[14]
[13]
好的,您关心查询工厂是如何工作的,所以
我们会调查一下的。让我们通过两个步骤来讨论
第二个问题中的传递搜索。最初的目录
执行请求的初始不及物搜索:查找关系
贝蒂是他们的主管。那是黛安娜和埃德加。
现在,对于每个结果,目录都要求查询工厂
下一步。我们带黛安娜去吧。目录对工厂说,
"考虑到贝蒂是主管的关系问题,我得到了
这是黛安娜的结果。你还有其他问题要问吗
再往前看?"。工厂还获取目录实例,因此
如果需要,可以用它来回答问题。
好吧,下一部分是你的大脑受伤的地方。坚持住,
在我们的例子中,工厂看到查询是针对主管的。它的
另一个键,它所转换的键是
zc.relation.relation
。< EM >
factory获取当前令牌的转置密钥结果。so,for
us,
zc.relation.relation
的一个键实际上是一个no op:结果
是
现在的代币,黛安娜。然后,工厂有了自己的答案:更换旧的
查询中的supervisor值betty,结果为diane。下一个
传递查询应该是{'supervisor','diane'}。TA D. < /P>
< COL/> < COL/>
<正文>
< >
<表>
我们将如何转储和加载关系:使用"注册表"
对象,类似于intid实用程序。
[15]
[14]
这里我们将设置一个zodb实例供我们使用。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
14
< COL/> < COL/>
<正文>
< >
<表>
在这个"dump"方法的实现中,我们使用缓存来
告诉你如何使用它。这工作可能有点过分了,
甚至可能会失去速度,但你可以看到这个想法。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
18
现在我们可以创建一个关系目录来保存这些项目。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
19
现在我们建立索引。我们从组织开始,然后
用它们建立目录。这部分将类似于示例
在readme.rst中,但是将引入更多关于优化和
令牌。然后我们将添加关于角色的部分,并探索查询和
基于令牌的"连接"。
组织
组织将拥有一组组织。这实际上不是
在zodb中本来就很容易,因为这意味着我们需要比较
或者散列持久对象,这些对象随着时间的推移不能可靠地工作,并且
把机器从盒子里拿出来。为了回避这个例子的问题,
还是做一些有点意思的真实的事情,我们会用
上面介绍的注册表标记。这也会给我们一个机会
再多谈谈优化和令牌。(如果你愿意
要以理智和透明的方式保存一组持久对象,请尝试
尚未设置包xxx。)
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
20
好的,现在我们知道组织将如何运作。现在我们可以添加
部分
目录索引。这将从我们添加的
自述文件中的索引。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
21
那么,与自述示例有什么不同?
首先,我们使用一个接口元素来定义要索引的值。
它提供了一个接口,对象将被适应,一个默认名称
对于索引,以及有关是否应使用该属性的信息
直接或致电。
其次,我们没有指定转储或加载。他们没有。这个
意味着索引值已被视为标记。这个
如果索引为
值是使用与
索引–这将引出下一个差异。
第三,我们指定
multiple=true
。这意味着
在一个给定的关系上,提供或能够适应组织将
收集
部分。这些永远都是一套,
实际colection是btrees集还是btree的键。
最后,我们指定一个用于查询的名称。我发现这些疑问
当查询键是单数时更容易阅读,因此我经常重命名复数。
在自述文件中,我们可以添加另一个简单的转置传递查询
工厂,在"部分"和"无"之间切换
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
22
让我们在查找的层次结构中添加几个搜索索引…
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
23
…向下。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
24
请注意:搜索索引实际上不是一个好主意。这个
索引是为向下查找而设计的。
[15]
这里有一个简单的持久密钥引用。注意它是
不是持久的:这对解决冲突很重要
能够工作(我们在这里没有展示,但我们试着靠得更多
走向实用对于本例)。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
15
这是一个简单的整数标识符工具。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
16
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
17
< COL/> < COL/>
<正文>
< >
<表>
让我们创建并添加一些组织。
我们将创建这样的结构
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
26
这是蟒蛇。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
27
现在目录知道了这些关系。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
28
而且,现在我们可以搜索了。为此,我们可以使用一些
T他提供目录。最常用的是tokenizequaly。它需要一个
使用未标记化的值进行查询并将其转换为
标记化。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
29
当然,现在单独用"part"做这个有点傻,因为
不会在关系目录中更改(因为我们说过dump和
负荷
无
,如上所述。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
30
tokenizequery方法非常常见,我们将把它分配给
我们例子中的变量。然后我们将进行一两次搜索。
所以…找出YNOD开发人员管理的关系。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
31
好吧…我们使用了findrelationtokens,而不是findrelations,所以
现在是几个数字。我们如何将它们转换回来?
ResolveRelationTokens
将起作用。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
32
resolvequery
是tokenizequaly的镜像:它转换
标记化查询到具有"加载"值的查询。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
33
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
34
同样,
tokenizerelations
是
resolvereationtokens
的镜像。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
35
其他与令牌相关的方法如下
[17]
:
[16]
transmissingTransitiveMembership索引
提供ISearchindex。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
25
< COL/> < COL/>
<正文>
< >
<表>
-
tokenizevalues
,它返回值的一个iterable标记
给定索引名的;
-
resolveValueTokens
,它返回
给定的索引名;
-
标记化
,返回给定关系的标记;和
-
ResolveRelationToken
,它返回给定令牌的关系。
为什么我们要用这些代币,而不是把它们藏起来
使api更漂亮?通过曝光它们,我们可以实现高效的连接,
以及在其他情况下的有效使用。例如,如果您使用相同的
intid实用程序在其他目录中标记,我们的结果可以合并
其他目录的结果。同样,您可以使用结果
对其他目录的查询-甚至从
正在查询此目录-作为此处的查询值。我们将在
下一节。
角色
我们已经建立了组织关系。现在让我们设置角色,然后
实际上能够回答我们在开头描述的问题
文件的。
在我们的roles对象中,roles和principal只是字符串–id,如果
这是一个真正的系统。组织将是直接的对象引用。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
40
现在,让我们将值索引添加到关系目录中。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
41
这些是我们在
addvalueindex
以前,但所有的混合和匹配相同的成分。
提醒一下,我们的组织结构如下:
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
26
现在,让我们创建并添加一些角色。
< Buff行情>
αααα143
现在,我们可以开始进行搜索了。
[17]
对于它的价值,这里有一些小的
其余令牌相关方法的示例。
这两个是
tokenizerelations
和
解决关系令牌
标记化
返回给定关系的标记。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
36
ResolveRelationToken
返回给定令牌的关系。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
37
现在"价值观"的表现有点蹩脚,因为唯一的价值观
我们现在没有标记化,而是直接使用。但是这里
去,显示一些迷人的禁止操作。
tokenizevalues
,返回
给定的索引名。
αααα138
resolveValueTokens
返回
给定的索引名。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
39
< COL/> < COL/>
<正文>
< >
<表>
奥菲莉亚的角色设置是什么?
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
45
这个答案不需要传递:我们完成了。
下一个问题。奥菲莉亚在哪里扮演"作家"的角色?
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
46
好吧,这是不及物的。我们需要传递查询吗
工厂?不!这是一个很好的机会来看看我们谈过的
关于上一节。这实际上应该是两个步骤
行动:找到所有奥菲莉亚有作家的组织,
然后找到该组织的所有可传递部分。
< Buff行情>
αααα147
更像是这样。
下一个问题。哪些用户在"zookd devs"组织中有角色?
不及时性,这很容易。
< Buff行情>
αααα148
在传递性方面,我们应该执行另一个连接。
< Buff行情>
αααα149
这有点尴尬,但它确实起到了作用。
< dl >
最后一个问题,以及开始整个示例的问题。
奥菲莉亚在"Zookd NBD"组织中扮演什么角色?
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
50
不及时性,这是正确的。但是,从传递的角度来说,奥菲莉亚也有
评论员和作者,这是我们希望能够快速得到的答案。
我们可以用另一种方式来提问,然后,再次利用join。
我们将它设置为一个函数,因为我们稍后将要使用它
不重复代码。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
51
如您所见,使用令牌使有趣的连接成为可能,
只要两个查询中的标记相同。
我们已经研究了标记方法和标记技术,比如连接。实例
我们讲的故事可以让我们进入一些更高级的话题,比如
查询工厂连接并搜索可以提高读取速度的索引。
查询工厂连接
我们可以建立一个查询工厂,使连接自动进行。查询
factory是一个带两个参数的可调用函数:一个查询
开始搜索)和目录。工厂要么不退货,
指示查询工厂不能用于此查询,或
返回另一个接受关系链的可调用函数。最后
关系链中的令牌是最新的。这个的输出
内部可调用的
btrees.family32.oo.bucket查询以从给定链进一步搜索
关系的。
这是解决这个问题的一个有缺陷的方法。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
52
这对我们当前的示例有效。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
53
但是,对于其他类似的查询,它将不起作用。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
54
有缺陷的工厂实际上是更典型的关系的有用模式
遍历。从一种关系到另一种关系,奥菲莉亚
一直到高层都有联系。然而,安倍只有
顶部,因此没有任何东西被遍历。
相反,我们可以创建一个查询工厂来修改初始查询。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
55
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
56
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
57
这种方法和另一种方法的区别在于
不及物的:这个查询工厂修改初始查询,然后
不要再问了。目录当前总是停止调用
如果查询不返回任何结果,因此
有缺陷的工厂根本无法解决此类问题。
我们可以将此查询工厂添加为另一个默认值。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
58
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
59
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
60
以前安装的查询工厂仍然可用。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
61
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
62
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
63
查询工厂联接的搜索索引
现在我们已经编写了一个封装连接的查询工厂,我们可以
使用加快搜索速度的搜索索引。我们只使用传递搜索
迄今为止的索引。现在我们将添加一个不及物搜索索引。
不及物搜索索引通常只需要搜索值
名称应该是索引,结果名称(默认为
关系),并且可以选择要使用的查询工厂。
我们需要使用两个额外的选项,因为我们是
做。我们需要指定组织和主体id值需要什么
当对象被索引时被更改,并且我们需要指出
应在组织、负责人id、
或
部件更改时更新。
getvaluetokens
指定需要索引的值。它得到
索引、所需令牌的名称、令牌、目录
生成了令牌更改(它可能与索引的
catalog,包含值字典的源字典
如果不重写标记,则将用于标记
此标记的附加值(键是值名),是
已删除此标记的值,以及是否已删除该标记。
方法不能返回none,这将使索引保留为默认值
在没有使用查询工厂的情况下应该有效的行为;或者
值:
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
64
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
65
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
66
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
67
[18]
我们还可以更多地显示值标记方法
现在清醒。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
44
< COL/> < COL/>
<正文>
不及物搜索索引提供
iArchindex和iListener。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
68
< >
<表>
现在我们可以改变和消除关系,包括组织和角色
使索引保持正确状态。考虑到
组织–
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
26
–首先,我们将把ynod dev移到zookd dev下面,然后退出。本遗嘱
简要地给予Y3L4项目和其他项目ABE完全特权。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
70
作为另一个例子,我们将改变安倍的角色,并看到它是
向下传播到zookd nbd。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
71
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
72
请注意,搜索索引顺序很重要。在我们的例子中,我们的不及物搜索
索引依赖于我们的传递索引,因此传递索引需要
先来。在名称之前需要可传递关系索引。马上,
你负责这个订单,很难想出一个
可靠的猜测算法。
侦听器、目录管理和跨关系目录加入
到目前为止,我们已经用一个索引目录完成了所有示例
两种关系。如果我们想要两个目录
同质的关系集合?感觉很干净,但也很干净
引入一些新的皱纹。
让我们使用当前的组织目录,删除多余的
信息;并为角色创建一个新角色。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
73
我们需要一个稍微不同的查询工厂和一个稍微不同的
搜索索引
getvaluetokens
函数。我们将编写这些,然后修改
为新世界配置两个目录。
我们在这里编写的可传递工厂用于角色目录。资讯科技成功
访问组织目录。我们可以做很多
方法-依赖实用程序,或从上下文中查找目录。我们将
使角色目录具有.org目录属性,并依赖该属性。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
74
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
75
如果你在代码中跟随并与原件进行比较,你可以
要知道,这种方法比关系
在同一目录中。
现在我们将修复组织目录
< COL/> < COL/>
<正文>
< >
<表>
这还显示了如何使用RemoveDefaultQueryFactory和RemoveSearchIndex
方法
[20]
在我们修改它们之前,让我们看看我们制作的副本。
副本当前的行为应与原件相同。
αααα176
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
77
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
78
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
79
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
80
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
81
αααα182
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
83
< COL/> < COL/>
<正文>
< >
<表>
现在我们将设置角色目录
[21]
通过删除查询会得到错误
未注册的工厂。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
84
< COL/> < COL/>
<正文>
对一个副本的更改不应影响另一个副本。那
意味着角色目录仍应像以前一样工作。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
85
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
86
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
87
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
88
< >
<表>
新的角色目录索引需要从组织目录更新。
我们将使用侦听器来设置,这是一个新概念。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
89
现在角色目录应该能够回答与旧目录相同的问题
单一目录法。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
90
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
91
我们还可以对目录和搜索索引进行更改
维护。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
92
αααα193
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
94
我们在这里添加一个新组织。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
95
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
96
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
97
现在我们将删除它。
< Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
98
要确保不及物复制看起来与我们期望的一样
< COL/> < COL/>
<正文>
< >
<表>
[23]
您可以多次添加侦听器。
>>> employees = {} # we'll use this to resolve the "name" tokens
>>> from functools import total_ordering
>>> @total_ordering
... class Employee(object):
... def __init__(self, name, supervisor=None):
... if name in employees:
... raise ValueError('employee with same name already exists')
... self.name = name # expect this to be readonly
... self.supervisor = supervisor
... employees[name] = self
... # the next parts just make the tests prettier
... def __repr__(self):
... return '<Employee instance "' + self.name + '">'
... def __lt__(self, other):
... return self.name < other.name
... def __eq__(self, other):
... return self is other
... def __hash__(self):
... ''' Dummy method needed because we defined __eq__
... '''
... return 1
...
99
现在,我们将删除侦听器,以显示我们的能力。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
00
删除我们没有的搜索索引也一样
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
01
< COL/> < COL/>
<正文>
< >
<表>
使用搜索索引:zc.relation catalog扩展示例
简介
本文档假设您已经阅读了readme.rst文档,并希望了解
再举个例子。在书中,我们将探讨一组关系
演示使用搜索索引和侦听器的大多数方面。
它不会解释其他文件已经涉及的主题。它
还描述了一个高级用例。
正如我们在其他文档中看到的,关系目录支持
搜索索引。它们可以根据需要返回任何搜索的结果。
当然,其目的是提供一个索引来优化
它声称的特定搜索。
searchindex模块提供一些搜索索引,优化
指定传递和不传递搜索。我们看到他们在工作
在其他文件中。我们将在本文档中对它们进行更深入的研究。
搜索索引通过"侦听器"接收消息来更新自身
接口。我们还将了解它的工作原理。
此文件中描述的示例检查类似于
zc.revision或zc.vault包:关系描述了
其他物体。因此,这是我们第一个
外部关系。
让我们建立一个例子故事一点。假设我们有一个图表,通常是
标记的层次结构-整数。关系指定给定的整数
令牌与其他整数令牌相关,包含表示或
其他含义。
整数还可以具有指定它们表示
一个或多个对象。
这允许我们有一个对象图,其中更改
图表不需要更改其余部分。因此,zc.revision和zc.vault
能够有效地为具有多个修订的图建模
有相当多的元数据支持合并。
让我们想象一个简单的层次结构。关系具有
标记
属性
还有一个
children
属性;children指向标记。关系会
用身份证证明自己。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
02
αααα203
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
04
标准TransportingTransitioneQueriesFactory将能够处理此问题
很好,所以我们用它作为索引。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
05
现在,让我们快速创建一个层次结构并将其索引。
< Buff行情>
αααα206
[25]
该层次结构是任意的。以下是我们的代币
指向子对象:
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
07
12个关系,标记0到11,总共33个标记,
包括孩子们。12个关系的id是100到111,
对应于0到11的标记。
没有可传递的搜索索引,我们可以得到所有可传递的结果。
结果是迭代器。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
08
αααα209
[26]
也可以进行转换,并且将
使用可传递的搜索索引,如下所示。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
10
FindRelationtokenChains
不会改变,但我们会将其包含在
讨论和示例来说明这一点。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
11
可传递的搜索索引
现在我们可以添加几个传递搜索索引。我们来谈谈
先说一点。
目前有一种传递索引,它将
转换传递查询的关系和值搜索
工厂。
索引只能在特定条件下使用。
< Buff行情>
-
搜索不是对关系链的请求。
-
它没有指定最大深度。
-
不使用过滤器。
如果是值搜索,则在
使用目标筛选器或目标查询,但基本关系索引可以
在这种情况下仍然使用。
搜索索引的使用在很大程度上是透明的:设置它们,以及
关系目录将它们用于使用更多
以前是蛮力。与外部用途的唯一区别是
使用索引的结果通常是btree结构,而不是
迭代器。
为关系添加可传递索引时,必须指定
查询的可传递名称(或名称),反之亦然。
这就是我们现在要做的一切。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
12
现在我们应该安装一个搜索索引。
注意我们是从父母那里(托克n)对儿童:该指数主要是
旨在帮助在层次结构中传递成员身份搜索。用它来
索引父项将为不太成功而招致大量写开销。
您可以在这里指定更多内容:查询的静态字段
做一些过滤。在这个例子中,我们不需要这些。
现在,目录如何使用此索引进行搜索?三种基本方式,
根据搜索的类型、关系、值或
canfind
。
在我们开始调查内部结构之前,让我们验证一下
我们期望的是:正确的答案,而不是迭代器,而是树结构。
< Buff行情>
αααα213
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
14
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
15
[27]
注意,最后两个
可以从
当我们浏览这些没有索引的示例时,不要使用
索引,所以我们不在这里显示它们:它们看起来方向不对
此索引。
那么这些结果是如何发生的呢?
第一个,
findrelationtokens
和最后一个,
canfind
是最多的
直截了当。索引查找与给定的
查询,不及时性。然后为每个关系查找索引
该标记的传递结果。最终的结果是所有人的联合
从不及物搜索中找到的索引结果。
可以找到
将结果转换为布尔值。
findValueTokens
与上面的相同,只需再多做一步。后
计算关系的并集,该方法返回
为所有找到的关系设置请求的值。
当关系重新建立索引时,它将保持自身。
< Buff行情>
αααα216
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
17
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
18
αααα219
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
20
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
21
复制索引时,将复制搜索索引。
< Buff行情>
αααα222
帮助程序
在编写搜索索引和查询工厂时,通常需要完成
访问关系目录数据。我们已经看到许多这样的工具:
getrelationmoduletools
获取所需btree工具的字典
处理关系。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
23
只有当btree是i*或l*模块时,"multiunion"才存在。
使用zc.relation.catalog.multiunion助手函数执行
对于给定的工具集,您可以进行最佳组合。
getvaluemoduletools
对索引值也一样。
< Buff行情>
αααα224
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
25
getrelationtokens
可以返回目录中的所有令牌。
< Buff行情>
αααα226
这也恰好相当于一个空的
查询,
αααα227
它还可以返回与给定查询匹配的所有标记,如果
没有匹配项。
αααα228
这也恰好相当于查询的
findrelationtokens
,
最大深度为1,没有其他参数。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
29
除非没有匹配项,
findrelationtokens
返回一个空
set(因此它总是返回iterable)。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
30
< DL>
-
getvaluetokens
可以返回中给定值名称的所有令牌
目录。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
31
这与仅具有名称(或
空查询,最大深度为1)。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
32
它还可以返回给定令牌的值。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
33
这与catalog.findValueTokens相同,后者具有名称和查询
{无:标记}。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
34
除非没有匹配项,
findValueTokens
返回一个空
set(因此它总是返回iterable);而getvaluetokens将
如果关系没有值(或关系未知),则返回none。
αααα235
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
36
< DL>
屈服关系ntokenchains是使用a的搜索的搜索主力
查询工厂。待办事项:描述。
[24]
在《2001:太空漫游》中,许多人相信哈尔这个名字
被选中是因为它是IBM的Rot25…我有时会作弊
使用rot1,因为结果听起来更好。
< COL/> < COL/>
<正文>
< >
<表>
[25]
查询工厂知道何时不需要它–不仅如此
当它的两个名字都没有被使用,而且当它的两个名字都是
使用。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
37
< COL/> < COL/>
<正文>
< >
<表>
<当值与它们的令牌相同时,
findValues
返回与
findValueTokens
相同的结果。在这里
我们看到这个没有索引。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
38
< COL/> < COL/>
<正文>
再次,当值与其令牌相同时,
findValues
返回与
findValueTokens
相同的结果。在这里
我们可以通过索引看到这一点。
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
38
< >
<表>
优化关系目录的使用
在以下方面有一些最佳实践和优化机会
目录。
-
尽可能使用带整数键的btree集。他们可以用树
多联合
以提高速度。整数cmp是可靠的,在c中。
-
永远不要使用持久对象作为键。它们将导致
当您需要查看它们时,它们占用内存和对象缓存,并且
他们(截至本文撰写时)禁用冲突解决。Intids(或类似)
是表示对象的最佳选择,以及一些其他不可变的,如
字符串是下一个最佳匹配,zope.app.keyreferences(或类似的)是
之后。
-
尽可能在查询中使用多个标记值,特别是在
传递查询工厂。
-
在加载和转储令牌时使用缓存,并在
传递查询工厂。
-
如果可能,不要加载或转储令牌(可以使用值本身
作为标记)。当您有多个令牌时,这一点尤其重要:
将它们存储在与zc.relation模块相同的模块中的btree结构中。
价值。
对于某些操作,特别是在
单个关系值,其中一些优化可以加快
常见情况下,重新编制索引的工作次数约为100次。
最简单(也可能最不有用)的优化是
单个操作生成的调用和所有加载调用共享一个缓存
每个调用类型的字典(转储/加载),每个索引关系值。
因此,例如,我们可以保存intids实用程序,以便
只需执行一次实用程序查找,此后它只
单字典查找。这是默认的
generatetoken
和
resolvetoken
函数在zc.relationship的index.py do中:查看它们
例如。
进一步的优化是根本不加载或转储令牌,而是使用值
那可能是代币。如果令牌具有
_ c语言中的cmp_uuu(或等效的),如ints之类的内置类型。指定
此行为将创建一个索引,其中包含
索引属性描述显式设置为"无"。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
40
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
41
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
42
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
04
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
44
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
45
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
46
如果你有成百上千的关系
对象,如果值是相同的"倍数",则可能是一个巨大的胜利
键入作为给定属性的存储btree。默认btree
属性的族是ifbtree;iobtree也是一个不错的选择,并且可以
在某些应用中更受欢迎。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
47
重新编制索引是可以实现一些重大改进的地方。以下
回转操作优化代码。
BLOCKQuo>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
48
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
49
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
50
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
51
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
52
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
53
TokenIzeValues和ResolveValueTokens在没有加载程序和
翻车机-也就是说,它们什么也不做。
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
54
更改
1.1.post2(2018-06-18)
-
另一次尝试使用正确的预期元数据语法修复PYPI页。
1.1.post1(2018-06-18)
-
使用正确的rest语法修复pypi页面。
1.1(2018-06-15)
-
添加对Python3.5和3.6的支持。
1.0(2008-04-23)
这是zc.relation包的初始版本。然而,它
表示另一个包zc.relationship的重构。这个
包仅包含关系(发货)索引的修改版本,
现在称为目录。zc.relationship索引的重构版本
依赖于(子类)此目录。ZC.关系也保持
向后兼容的子类。
这个包只依赖于zodb、zope.interface和zope.testing
软件,可以在标准zodb数据库内部或外部使用。
不过,软件必须在那里(软件包非常依赖
在zodb btrees包中)。
如果要将旧的zc.relationship索引切换到
关系目录,在你的generations脚本中试试这个技巧。
假设旧索引是
旧的
,则应创建以下行
一个新的zc.relation目录,包含您的旧数据:
< Buff行情>
>>> def dumpEmployees(emp, catalog, cache):
... return emp.name
...
55
为什么相同的基本数据结构现在称为目录?因为我们
暴露了改变数据结构的能力,以及
添加和删除是索引。把索引放进去是没有意义的
索引,但将索引放入目录中确实有意义。因此,A
更名诞生。
这个包中的目录与前面的有几个不兼容
关系索引和许多新特性。zc.relationship包
维护向后兼容的子类。以下讨论
将zc.relation目录与zc.relationship 1.x索引进行比较。
与zc.relationship 1.x索引不兼容
两大变化是方法名现在引用的是
关系
而目录的实例化方式略有不同
从索引中。其他一些变化值得你注意。这个
下面的列表试图突出显示所有不兼容项。
<表>
< COL/>
< COL/>
<正文>
< >
<表>
更改和新功能
-
目录现在提供了索引
搜索。索引必须显式实例化和注册
你想优化。当搜索值时,当
搜索关系,或确定两个对象是否
链接的。它不能用于关系链。请求索引
通常需要权衡更大的存储空间和更慢的写入速度
加快搜索速度。注册搜索索引已完成
在实例化时间之后;您可以迭代当前设置
使用,并移除它们。(代码路径希望支持遗留的
所有这些api的关系索引实例。)
-
现在可以在创建目录后指定新值,重复
超过所使用的设置,然后删除值。
-
目录有一个复制方法,可以在没有实际操作的情况下快速创建新的副本
必须重新建立关系索引。
-
查询参数现在可以通过
使用zc.relation.catalog.any(1、2、3、4)或
zc.relation.catalog.any((1,2,3,4))。
-
目录支持通过传递callables而不是
接口元素(仍受支持)。
-
findrelations
和新方法
findrelationtokens
可以找到
传递和不传递的关系。
芬兰
当以非及时性方式使用时,重复旧的zc.relationship索引
findrelationtokenset的行为。
(
findrelationtokenset
保留在api中,而不是弃用
要
findValueTokenSet
)
-
在findValues和findValueTokens中,
query
参数现在是可选的。如果
在布尔上下文、所有值或值中,查询的计算结果为false
返回标记。值标记使用
基础btree存储。然后可以直接用于其他btree
操作。
-
全新的文档。不幸的是,仍然不够好。
-
该软件包大大减少了ZC的直接依赖关系。
它现在更明显是一个zodb工具,除了
zope.testing和zope.interface。
-
侦听器允许对象侦听来自目录的消息(可以
直接使用,或用于触发事件。
-
您可以使用zc.relation.relation…键来搜索关系。
真的没有别名。对不起的。但是嘿,用常量!我想是的
更具可读性。
-
tokenizequery(和resolvequery)现在接受关键字参数作为
普通dict查询的替代方法。这可以使构造查询
更吸引人一点(即,
query=catalog.tokenizequery;
res=
catalog.findValues('object',
查询(subject=joe,predicate=owns))
)。
大不相容性:
-
FindRelationshipTokenSet
和
FindValueTokenSet
重命名为
一些稍有不同的语义,如
getrelationtokens
和
获取值标记
。结果与
可以使用
findrelationtokens(查询,1)
(其中1是maxdepth)。相同的
结果as
findValueTokenSet(relToken,name)
可以通过
findValueTokens(名称,{zc.relation.relation:relToken},1)
-
FindRelations
取代了FindRelationships。新方法将使用
如果已设置DefaultTransitiveQueriesFactory且MaxDepth不是1,则为它。
它共享
findrelationchains
的调用签名
-
islinked
现在可以找到
-
目录实例化参数已从旧索引更改。
-
加载
和
转储
(以前的
加载rel
和
转储rel
,
现在分别是实例化所必需的参数。
-
唯一的选择自变量是
btree
(was
relfamily
)和
系列
。现在指定要索引的元素
添加值索引
-
还要注意,
addvalueindex
默认为无加载和转储功能,
与旧的实例化选项不同。
-
查询工厂不同。请参见接口中的iqueryfactory。
-
它们首先获取(query、catalog、cache),然后返回一个getquerys
可调用的,获取重新链接并生成查询;如果查询
不匹配。
-
它们还必须处理空的重新链接。通常这应该
返回原始查询,但也可以用于对
原始查询。
-
它们不再被认为是可传递的查询工厂,而是
常规查询变异器。
中等:
-
目录不再继承自
zope.app.container.contained.contained.
-
索引要求zodb 3.8或更高版本。
小:
-
deactivatesets
不再是一个实例化选项(它已被破坏
因为一个zodb错误,正如
文档)。
内容
- 关系目录
- 概述
- 历史记录
- 设置关系目录
- 创建目录
- 添加关系
- 1.1.post2(2018-06-18)
- 1.1.post1(2018-06-18)
- 1.1(2018-06-15)
-
1.0(2008-04-23)
- 与zc.relationship 1.x index不兼容
- 更改和新功能
概述
关系目录可用于优化不及物性和及物性。 搜索有限预设维度的n元关系。
例如,可以为简单的双向关系编制索引,如employee to supervisor;主谓宾语的rdf式三元组;以及更复杂的 主谓宾语与上下文和状态的关系。这些 可使用传递行为的变量定义进行搜索。
目录可以在zodb中使用,也可以单独使用。它是一个普通的,相对来说 免政策工具。
它通常被用作更专业和 受约束的工具和api。三个这样的工具是zc.relationship容器, plone.relations容器和zc.vault。包裹里的文件, 包括这个,请描述其他可能的用途。
历史记录
这是对zc.relationship包的zodb-only部分的重构。 具体来说,zc.relation目录在很大程度上等同于 关系指数。zc.relationship 2.x行中的索引是 几乎完全向后兼容的zc.relation目录包装。 ZC.关系将继续保持,尽管积极的发展 希望进入ZC.关系。
许多想法来自与凯西邓肯的讨论和代码,特雷斯 西弗、肯·曼海默等等。
设置关系目录
在本节中,我们将介绍以下想法。
- 关系是具有索引值的对象。
- 您可以向关系目录添加值索引,以便能够进行搜索。价值观 可以用可调用或接口元素标识到目录。这个 索引值必须作为单个值或 收藏。
- 关系及其值作为标记存储在目录中:唯一 可以解析回原始值的标识符。整数是 最有效的代币,但其他代币也可以正常工作。
- 令牌类型决定所需的btree模块。
- 必须定义自己的标记化和解析标记的函数。这些 函数在关系和每个 它们的价值指数。
- 关系用 索引 索引
我们将使用一个简单的双向关系作为例子。简介 到一个更复杂的rdf样式主谓对象可以稍后找到 在文档中。
创建目录
想象一个从一个值到另一个值的双向关系。假设我们 建立员工与上司之间的关系:员工可以 有A单一主管。在第一个例子中, 雇员和主管是内在的:雇员有一个指针指向 主管和employee对象本身表示关系。
更进一步说,为了简单起见,员工姓名是唯一的, 可用于代表员工。我们可以使用名称作为"标记"。
令牌类似于关系数据库中的主键。令牌是 识别物体的方法。它必须分类可靠,你必须能够写 在给定正确上下文的情况下可靠地解析为对象的可调用函数。在 zope 3、intid(zope.app.intid)和keyreferences(zope.app.keyreference)是 合理代币的好例子。
我们将在下面看到,您提供了一种将对象转换为令牌的方法,并 对象、关系和每个值索引的标记。 它们可以是完全相同的功能,也可以完全不同,具体取决于 您的需要。
对于速度,整数是最好的标记;其次是其他 不可变,如字符串;后跟非持久对象;后跟 持久对象。这个选择还决定了btree模块的选择,如 我们将在下面看到。
这是我们的玩具示例类。再说一次,我们将使用员工 名称作为标记。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...
因此,我们需要定义如何将员工转变为他们的代币。我们称之为 标记化一个"转储"函数。相反,将令牌解析为 对象称为"加载"。
转储关系和值的函数会得到几个参数。第一 参数是要标记化的对象。其次,因为有时候 提供上下文,就是目录。最后一个参数是 为给定搜索共享。字典可以被忽略,或者用作缓存 用于优化(例如,保存您查找的实用程序)。
在这个例子中,我们的函数很简单:我们说令牌 员工姓名。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
如果持久地存储关系目录(例如,在zodb中),请注意 您提供的可调用函数必须是可选择的——模块级函数, 例如。
我们还需要一种方法将代币转换为员工,或"加载"。
"load"函数获取要解析的令牌;目录 上下文;和dict缓存,用于优化后续调用。
您可能已经注意到我们的 员工中有一个映射 在 employees global dict中要反对的名称的 类定义)。我们将使用它来解析令牌。
< Buff行情>>>> def loadEmployees(token, catalog, cache): ... return employees[token] ...
现在我们知道的足够多了,可以开始目录了。我们将实例化它 通过指定如何标记关系,以及什么样的btree模块 应该用来存放代币。
你如何选择btree模块?
- 如果令牌是32位整数,请选择 btrees.family32.ii , btrees.family32.if 或 btrees.family32.io
- 如果令牌是64位整数,请选择 btrees.family64.ii , btrees.family64.if 或 btrees.family64.io
- 如果它们是其他的,请选择btrees.family32.oi, btrees.family64.oi 或 btrees.family32.oo (或 btrees.family64.oo –它们是相同的。
在这些规则中,选择有点武断,除非您计划合并 这些结果与使用特定btree的另一个源的结果相同 模块。btree set操作只能在同一个模块中工作,因此必须 将模块与模块匹配。目录默认为if树,因为 标准的zope目录使用。这是最合理的选择 如果您的令牌实际上与 zope目录,您需要执行一些设置操作。
在本例中,我们的标记是字符串,因此我们需要oo或oi变体。我们会 丘se btrees.family32.oi,任意。
< Buff行情>>>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)< COL/> < COL/> <正文> < > <表>
[1] | 目录提供了iCalog。 >>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True |
在本例中,关系本身表示雇员,因此我们不需要 单独编制索引。
但我们需要一种方法告诉目录如何找到 关系,主管。可以使用属性将其指定给目录 或从zope.interface接口指定的方法,或使用可调用的方法。 我们暂时用一个可呼叫的。可调用的将接收索引关系 以及上下文目录。
< Buff行情>>>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...
我们还需要指定如何标记(转储和加载)这些值。在 在这种情况下,我们可以使用与关系本身相同的函数。 但是,请注意,我们可以指定完全不同的转储和 为每个"值索引"或关系元素加载。
我们还可以指定调用索引的名称,但它将默认为 函数(或接口元素)的 现在就给我们。
现在我们可以添加"主管"值索引。
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)
现在我们有了一个索引。
[2] | zc.relationship索引的旧实例,在最新的 版本子类zc.relation catalog,用于在 内部数据结构。我们在这里指定它,以便 将dict转换为oobtree可以运行。 >>> catalog._attrs = dict(catalog._attrs) |
添加关系
现在让我们创造一些员工。除了一个以外,其他人都有主管。 如果您回忆起我们的玩具employee类,则 构造函数是雇员名称(因此也是标记),并且 可选的第二个参数是主管。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...4
这是层次结构图。
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...5
让我们使用 索引 方法告诉目录有关关系的信息。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...6
我们现在已经创建了关系目录并向其中添加了关系。我们准备好了 搜索!
搜索
在本节中,我们将介绍以下想法。
- 对关系目录的查询由dict组成。
- 查询键是要搜索的索引的名称,或者 精确关系的特例,常数
-
查询值是要匹配的结果的标记;或者
无
,
指示将
none
作为值(或空集合)的关系,
如果是倍数)。搜索值可以使用
zc.relation.catalog.any(args)或 zc.relation.catalog.any(args) none)结果以匹配给定的密钥。 - 索引有多种方法可帮助您使用标记。 tokenizequery 通常是最常用的,尽管其他可用。
- 要查找与查询匹配的关系,请使用 findRelations 或 findrelationtokens
- 要查找与查询匹配的值,请使用 find values 或 findvalues
- 您可以使用查询工厂进行传递性搜索。这个 zc.relation.queryfactory.transportingtransitive 是一个很好的常见情况 允许您在层次结构中上下移动的工厂。查询工厂可以是 作为参数作为 queryfactory 传递给搜索方法,或 作为默认行为安装,使用 addDefaultQueryFactory
- 要查找查询的关联方式,请使用 findRelationChains 或 FindRelationtokenchains
- 要确定查询是否相关,请使用 canfind
- 循环传递关系被处理以防止无限循环。他们 在 findrelationchains 和 findrelationtokenchains 中用 a zc.relation.interfaces.icircularrelationpath 标记接口。
-
搜索方法共享以下参数:
- 最大深度 ,限制搜索的传递深度;
- 过滤,允许代码过滤可传递路径;
- targetquery ,允许查询根据 终点的;
- targetfilter ,允许代码根据 端点;和
- 上述queryfactory 。
- 您可以设置搜索索引以加速特定的可传递搜索。
查询、 查找关系和特殊查询值
那么谁为爱丽丝工作呢?这意味着我们想要得到关系 员工-由Alice的主管担任。
目录问题的核心是查询。拼写查询 作为字典。主要的意思是字典里的键 指定索引名称,值指定约束。
查询中的值总是用标记表示的。目录中有 好几个帮手来减轻这件事的负担,但现在让我们 我们的代币易于理解的优势。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...7
艾丽斯是贝蒂和查克的直接上司。
如果你想问"谁不向任何人报告?""那么你想 找一个没有主管的关系。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...8
爱丽丝是唯一一个不向任何人报告的雇员。
如果你想问"谁向黛安或查克报告?""然后你用 zc.relation any 类或 any 函数传递多个值。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...9
弗兰克、盖林和豪伊都向黛安娜或查克汇报。 [4]
[3] | 添加值索引可以生成多个 例外情况。 您必须同时提供转储和加载,或者两者都不提供。 >>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither 在这个例子中,即使我们修复了它,我们也会得到一个错误,因为我们已经 已为主管功能编制索引。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...0 您也不能在同一名称下添加其他函数。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...1 最后,如果函数没有名称 提供一个,您不能添加索引。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...2 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...3 |
查找值 和 关系 查询键
那么,我们如何找到谁是员工的主管呢?好吧,在这种情况下, 看看员工的属性!如果可以使用 通常会在ZODB中获胜。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...1
同样,正如我们在第一个例子开始时提到的,知识 对于员工实例来说,是"固有"的。它是 有可能,甚至很容易,问目录这种问题,但是 目录语法更适合于"外部"关系,例如 从主管到员工:两者之间的联系 主管对象及其员工与主管无关,因此 你可能想要一个目录来找到它!
但是,我们将非常简要地探讨语法,因为它引入了 一对重要的搜索方法,因为它是一块垫脚石 第一次传递搜索。
那么,关系目录,谁是豪伊的主管?
要问这个问题,我们需要从关系中获取索引值: 查找值 。在最简单的形式中,参数是 所需的值,以及一个查询,以查找具有所需的 值:
询问呢?上面,我们注意到查询中的键是 要搜索的索引。但是,在这种情况下,我们不想搜索 与往常一样,更多用于匹配关系的索引,但实际上指定了一个关系: Howie .
我们没有值索引名称:我们正在查找关系。查询 那么,键应该是常数zc.relation.relation 。为我们的当前 例如,这意味着查询是 {zc.relation.relation:'howie'}
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...2
恭喜,你刚刚发现 写"howie.supervisor"的方式效率低下! [5]
[4] | 任何 都可以比较。 >>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...0 |
[5] | 这里的令牌结果是相同的。 >>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...3 当我们在下面的脚注中,我会提到你可以 搜索尚未建立索引的关系。 >>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...4 |
更有用的是,您可以使用其他查询键和 关系。这问,"贝蒂,爱丽丝,弗兰克,谁是 由爱丽丝监督?"
" < Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...6
只有贝蒂是。
代币
如上所述,目录提供了几个使用令牌的助手。 最常用的是tokenizequery,它接受一个带有对象的查询 值并使用为注册的"dump"函数将其转换为令牌 关系和索引值。以下是一些 我们在上面遇到的问题。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...7
(如果你想知道最后一个结果中的 无 ,是的, zc.relation.relation 只是 none 的可读性糖。
所以,这里是一个使用 tokenizequery 的实际搜索。我们将为 catalog.tokenizequery 只是为了把事情缩短一点。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...8
目录总是有并行搜索方法,一种用于查找对象的方法,如 如上所示,其中一个用于查找令牌(唯一的异常是 canfind , 如下所述)。查找标记可以更有效,特别是如果 关系目录的结果只是查找路径的一步 你想要的结果。但对于某些常见情况,查找对象更简单。 下面是上面一些查询的快速示例,获取标记而不是 对象。
您还可以使用关键字参数在
tokenizequery
中拼写查询。这个
如果您的键是
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...9
>>> def loadEmployees(token, catalog, cache): ... return employees[token] ...0
>>> def loadEmployees(token, catalog, cache): ... return employees[token] ...1
>>> def loadEmployees(token, catalog, cache): ... return employees[token] ...2
目录提供了其他几种仅用于处理令牌的方法。
- resolvequery :与tokenizequaly的倒数,转换 托克尼zedquery到带有对象的查询。
- tokenizevalues :返回给定 索引名。
- resolveValueTokens :返回 给定索引名。
- 标记化 :返回给定关系的标记。
- ResolveRelationToken :返回给定令牌的关系。
- 标记化 :返回给定关系的一个iterable标记。
- ResolveRelationTokens :返回令牌的一个Iterable关系 给定。
这些方法使用较少,并在 这个包裹。
传递式搜索、查询工厂和最大深度
所以,我们看到了很多一级的,不及物的搜索。怎么样 传递搜索?好吧,你得告诉目录怎么走这棵树。 在这种简单(非常常见)的情况下, zc.relation.queryfactory.transportingtransitive 将起作用。
可传递查询工厂只是目录用来调用的 问"我有这个问题,这是我找到的结果。我应该 可传递地再跨出一步,那么下一步应该搜索什么查询?" 写工厂比我们现在想说的要复杂得多, 但是使用transportingtransitionvequeryfactory很容易。你只要告诉我 它应该转换两个查询名,以便在 方向。
例如,这里我们只想告诉工厂把这两个键调换一下 我们使用了, zc.relation.relation 和"supervisor"。我们建个工厂吧, 在查询中使用它进行几个可传递的搜索,然后,如果需要, 您可以通过阅读脚注来了解正在发生的事情。
这是工厂。
< Buff行情>>>> def loadEmployees(token, catalog, cache): ... return employees[token] ...3
现在, 工厂 只是一个可调用的。让它来帮助回答几个问题 问题。
Howie所有的主管都是过渡性的(这在 图)
< Buff行情>>>> def loadEmployees(token, catalog, cache): ... return employees[token] ...4
贝蒂所监督的人都是谁,广度优先(这个 在图表中往下看?
< Buff行情>>>> def loadEmployees(token, catalog, cache): ... return employees[token] ...5
是的,看起来不错。那是怎么做到的?如果你在乎,读这个 脚注。 [13]
这个可传递的工厂实际上是唯一一个 需要这个特定的目录,所以连接它可能是安全的 作为违约。可以添加多个查询工厂以匹配不同的 使用 addDefaultQueryFactory进行查询
< Buff行情>>>> def loadEmployees(token, catalog, cache): ... return employees[token] ...6
现在默认情况下,所有搜索都是可传递的。
< Buff行情>>>> def loadEmployees(token, catalog, cache): ... return employees[token] ...7
我们可以使用 maxdepth [7]
[6] | 如果您使用 findValues 或 findValues令牌 如果试图指定一个未编入索引的值名,则会出现一个valueerror。 >>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...5 |
[7] | 使用a maxdepth进行搜索 不 queryfactory 引发错误。 >>> def loadEmployees(token, catalog, cache): ... return employees[token] ...8 >>> def loadEmployees(token, catalog, cache): ... return employees[token] ...9 >>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)0 |
我们将介绍一些其他可用的搜索 本文档和其他文档中稍后的参数。这很重要 注意 所有搜索方法都与 ``查找关系`` 。 findValues 和 findValues标记 只添加 指定所需值的初始参数。
我们看了两种搜索方法目前为止的ods:find值 findRelations 方法帮助您询问相关的内容。但是如果你 想知道事物是如何传递相关的吗?
查找关联链 和 目标查询
另一种搜索方法,findrelationchains,可以帮助您发现 事物之间存在传递关系。
方法名为"查找关系链"。但什么是"关系" "链"?在这个api中,它是关系的传递路径。为了 例如,豪伊的指挥系统是什么? 查找关联链 将返回每个唯一路径。
< Buff行情>>>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)3
仔细看看结果。注意,结果是 元组。每个元组是一个唯一的链,它可能是 后继链条。在这种情况下,最后一个链是最长的 最全面。
如果我们想看看爱丽丝的路怎么办?那就是一个 为每个受监督的员工提供链,因为它显示了所有可能的路径。
< Buff行情>>>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)4
这就是爱丽丝的所有道路,所有的锁链。我们把结果分类, 但通常情况下,它们是宽度优先的。
但是如果我们只想找到从一个查询结果到 另一个查询结果——比如,我们想知道爱丽丝的命令链 至于豪伊?然后我们可以指定一个 targetquery 来指定 所需终点的特征。
< Buff行情>>>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)5
所以,贝蒂监督黛安,黛安监督豪伊。
注意 targetquery 现在将 maxdepth 加入到我们的共享集合中 搜索我们介绍的参数。
过滤器 和 目标过滤器
我们现在可以快速查看两个共享搜索参数中的最后一个: 过滤器 和 目标过滤器 。这两个相似之处在于它们都是 在基于 不管你能编什么逻辑。它们的不同之处在于 过滤器进一步停止 从关系进行传递式搜索,而 targetfilter 仅省略 给定结果,但允许进一步搜索。就像targetquery,然后, 当您想指定路径的另一端时,targetfilter 很好。
例如,假设我们只想让女性员工返回。
< Buff行情>>>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)6
以下是所有由Alice过渡性地监督的女性员工,使用 目标滤波器
< Buff行情>>>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)7
以下是查克监督的所有女员工。
< Buff行情>>>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)8
作为过滤器使用的相同方法只会直接返回雌性 由其他女性监督-在这种情况下,不是Galyn。
< Buff行情>>>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)9
它们可以相互结合,也可以与其他搜索相结合 参数 [9]
[8] | 最大深度 必须是无或正整数,或者 否则您将得到一个值错误。 >>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)1 >>> import zc.relation.catalog >>> import BTrees >>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)2 |
>>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True0 < > <表>
搜索索引
在不设置任何额外索引的情况下, findRelations 和findValues方法本质上依赖于 对 findrelationchains 的蛮力搜索。结果是难以接受的 是逐渐计算出来的。例如,让我们重复这个问题 "贝蒂监督谁?"。注意 res 首先填充一个列表 有三个成员,但不会填充第二个列表。这个 迭代器已用尽。
< Buff行情>>>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True1
在许多情况下,这种方法的强大威力是足够的,但是 有时速度为搜索搜索至关重要。在这种情况下,你可以 添加"搜索索引"。搜索索引加快了 通过索引结果进行更精确的搜索。搜索索引可以 影响 findRelations中带有 queryfactory 的搜索结果, findValues 和即将推出的 影响 findrelationchains
relation包目前包含两种搜索索引,一种是 索引可传递成员在层次结构中的搜索和一个不可传递成员的搜索 此包中tokens.rst中探索的搜索,可以优化频繁 对复杂查询的搜索或可以有效地更改 不及物搜索。其他搜索索引实现和方法可能是 以后添加。
下面是一个非常简单的例子,为transitive添加一个搜索索引 上面显示的指定"主管"的搜索。
< Buff行情>>>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True2
zc.relation.relation 描述了如何沿着链返回。搜索 在searchindex.rst中对索引进行了合理的详细说明。
现在我们已经添加了索引,我们可以再次搜索。结果是这个 时间已经计算好了,所以,至少当你要求代币时,它 可重复。
< Buff行情>>>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True3
请注意,当使用索引时,宽度优先排序将丢失 [10]
传递循环(以及更新和删除关系)
可传递搜索和提供的搜索索引可以处理 周期。在当前示例中,周期的可能性比其他一些示例小, 但我们可以把这个案子再延伸一点:想象一个"伪装的国王" 高层的人在下级工作。也许是爱丽丝 为赞恩工作,为贝蒂工作,为爱丽丝工作。人工的, 但很容易画出来:
>>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True7
也易于创建。
< Buff行情>>>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True8
现在我们有一个循环。当然,我们还没有告诉目录。 索引 可用于重新索引alice和index zane。
< Buff行情>>>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True9
现在,如果我们问谁为贝蒂工作,我们就得到整棵树。(我们会问 对于令牌,只需查看较小的结果即可。) [11]
[10] | 我们在本文档中看到的场景显示了一个案例 其中搜索索引中的特殊逻辑需要寻址更新。 例如,如果我们将Howie从Diane移走 >>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True4 致Galyn >>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True5 然后,新位置和旧位置的搜索索引都是正确的。 >>> from zope.interface.verify import verifyObject >>> import zc.relation.interfaces >>> verifyObject(zc.relation.interfaces.ICatalog, catalog) True6 |
如果我们要找弗兰克的主管,包括贝蒂。
< Buff行情>>>> catalog._attrs = dict(catalog._attrs)3
findRelationChains返回的路径用特殊接口标记, 以及特殊元数据,以显示链。
< Buff行情>>>> catalog._attrs = dict(catalog._attrs)4
这是最后一条链:
< Buff行情>>>> catalog._attrs = dict(catalog._attrs)5
链的"cycled"属性具有创建循环的查询列表。 如果运行一个或多个查询,您将看到循环将 重新启动–路径将开始重叠的位置。有时是质疑 结果将包括多个循环,以及一些非循环的路径。 在本例中,只有一个循环查询,结果是 循环关系。
< Buff行情>>>> catalog._attrs = dict(catalog._attrs)6
>>> catalog._attrs = dict(catalog._attrs)7
消除这种疯狂"id="id13" rel="nofollow">[12],我们可以取消zane的索引,然后更改 重新索引爱丽丝。
[11] | 对贝蒂、爱丽丝和赞恩的查询结果都是 同样的。 >>> catalog._attrs = dict(catalog._attrs)0 循环不会污染循环外的索引。 >>> catalog._attrs = dict(catalog._attrs)1 >>> catalog._attrs = dict(catalog._attrs)2 |
可以找到
我们到了最后一个搜索方法: canfind 。我们得到了价值观 关系,但是如果你只是想知道 有联系吗?例如,爱丽丝是豪伊的主管吗?是 扔出?要回答这些问题,可以使用 canfind 方法 与 targetquery 搜索参数结合。
canfind方法的参数与findRelations相同。然而, 它只返回一个关于搜索是否有任何结果的布尔值。这个 是一种方便,还允许进行一些额外的优化。
贝蒂监督谁吗?
< Buff行情>>>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...4
豪伊呢?
< Buff行情>>>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...5
赞恩(不再是雇员)呢?
< Buff行情>>>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...6
如果我们想知道艾丽斯或查克是否监督豪伊 路径上两点的特征。问一个关于另一个的问题 在路径末尾,使用 targetquery
爱丽丝是豪伊的主管吗?
< Buff行情>>>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...7
查克是豪伊的主管吗?
< Buff行情>>>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...8
Howie Alice是他的雇员吗?
< Buff行情>>>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...9
豪伊·查克是他的雇员吗?
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)0
(注意,如果您的关系描述了一个层次结构,则向上搜索层次结构是 通常比向下搜索更有效,所以第二对问题是 在这种情况下,通常比第一种更好。)
使用更复杂的关系
到目前为止,我们的示例使用了一个简单的关系,其中索引对象 是关系的一端,对象上的索引值是另一端。 这个示例让我们查看了所有基本的zc.relation目录 功能。
不过,正如引言中提到的,目录支持 为更复杂的关系而设计。本节将快速检查 很少有其他用途的例子。
在本节中,我们将看到上面提到的一些想法的例子,但不是 但已演示。
- 我们可以使用接口属性(values或callables)来定义值 索引。
- 使用接口属性将导致尝试调整关系,如果 尚未提供接口。
- 在定义值索引时,我们可以使用 multiple 参数来指示 索引值是一个集合。
- 在定义值索引时,我们可以使用 name 参数来指定 要在查询中使用的名称,而不是依赖于接口的名称 属性或可调用。
- 在实例化catalog中的 family 参数允许您更改 关系和值索引的默认btree系列 btrees.family32.if 到 btrees.family64.if
外部双向关系
我们当前故事的一个简单变化是:如果索引关系 在另外两个物体之间——也就是说,如果关系是外在的 两个参与者?
假设我们有亲生关系。我们想要一个 "人"和"父母"关系。我们将为 iparentage 因此我们可以看到如何使用接口定义值索引 作品
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)1
现在我们将定义转储程序和加载程序,然后定义目录。通知THAT 我们依赖一种模式:在加载之前必须调用转储。
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)2
现在我们有一个完整的目录。让我们添加一些关系。
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)3
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)4
这是我们的一个层次结构图。
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)5
现在,我们可以索引这些关系,并提出一些问题。
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)6
多方向关系
上一个例子很快展示了如何为 外在的双向关系。相同的模式可以扩展为n路 关系。例如,考虑一个四向关系 主谓宾语[在上下文中]。例如,我们可以 想说"(乔,)在街角的商店里卖(甜甜圈,咖啡),"(乔,)" 是主语的集合,"sells"是谓语,"(甜甜圈,咖啡)" 是对象的集合,"corner_store"是可选上下文。
对于最后一个例子,我们将集成两个我们还没有看到的组件 以前的版本:zodb和改编版。
我们的示例zodb方法使用oid作为令牌。这可能在一些 如果您永远不支持多个数据库,并且不需要 抽象层,以便不同的对象可以具有相同的标识符。
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)7
(使用zope.component时, \u conform\uuu 通常是不必要的; 但是,此包不依赖于zope.component。)
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)8
>>> catalog.addValueIndex(supervisor, dumpEmployees, loadEmployees, ... btree=BTrees.family32.OI)9
如前所述, dumppersistent 和 loadpersistent 有点像玩具 上面。另外,虽然我们的谓词将存储为字符串,但是一些程序员 在这种情况下,可能更喜欢使用转储来验证字符串是否 以某种方式显式注册,以防止输入错误。显然,我们不是 为我们的例子而烦恼。
我们制造一些物体,然后我们与这些物体建立一些关系 为它们编制索引。
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither0
>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither1
>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither2
>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither3
现在我们可以问一个简单的问题。他们在哪里卖甜甜圈?
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither4
希望这些示例能为您提供有关如何使用此工具的进一步想法。
附加功能
本节介绍外围设备功能。我们将学习以下内容。
- 侦听器可以在目录中注册。当一个亲戚 添加、修改或删除;清除并复制目录时 (见下文)。
- clear方法清除目录中的关系。
- copy方法通过复制内部目录来复制当前目录 数据结构,而不是重新索引关系,它可以是 重大优化机会。这将复制值索引并搜索 索引;并给侦听器一个机会来指定 应该包含在新副本中。
- 五种相关搜索方法的ignoresearchindex参数 使搜索忽略搜索索引,即使有适当的 一个,
- findRelationTokens() (不带参数)返回所有 目录中的关系标记。
- findValueTokens(index_name) (其中"index_name"应替换为 索引名)返回目录中所有值标记的btree集 给定的索引名。
听众
当目录发生更改时,可能会有多种潜在的客户端需要得到警报。 zc.relation不依赖于zope.event,因此可以注册侦听器 各种变化。让我们做一个快速的演示监听器。 加法 和 removals 参数是{value name:iterable of added or的字典 远离的值标记}。
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither5
监听器可以多次安装。
侦听器可以作为持久弱引用添加,因此,如果它们是 在其他地方删除后,zodb包将不考虑目录中的引用 防止垃圾收集。
我们将把其中一个演示监听器作为 正常引用,默认行为。然后我们将展示一些示例消息 发送到演示侦听器。
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither6
>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither7
这些示例中没有显示的两个方法是 sourcecleared 和 已复制源代码 。我们很快就会看到下面的内容。
清除方法
clear方法只对目录中的所有关系进行索引。安装 侦听器已调用 sourcecleared 。
< Buff行情>>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither8
>>> catalog.addValueIndex(supervisor, dumpEmployees, None, ... btree=BTrees.family32.OI, name='supervisor2') Traceback (most recent call last): ... ValueError: either both of 'dump' and 'load' must be None, or neither9 α
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...00
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...01
复制方法
有时可能需要复制关系目录。一种方法是 若要创建新目录,请将其设置为当前目录,然后重新编制索引 同样的关系。这对程序员来说是不必要的慢,而且 计算机。copy方法用相同的 通过复制内部数据结构建立索引关系。
搜索索引被请求为新的 catalog;并且监听器有机会根据需要对新的 复制,包括安装它们自己和/或它们选择的另一个对象 作为听众。
让我们制作一个包含搜索索引和侦听器的填充索引的副本。 注意,在我们的侦听器中, sourcecopied 将自己作为侦听器添加到 新副本。这是在复制过程的最后完成的。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...02
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...03
现在,该副本拥有自己的内部数据结构和 搜索索引。例如,让我们修改关系并将新关系添加到 复制.< /P> < Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...04
原始目录未被修改。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...05
参数 ignoresearchindex 参数
可以使用搜索索引的五种方法, findValue , findValueTokens , findRelations , findRelationTokens ,以及 可以显式地请求canfind忽略任何相关的搜索索引 使用 ignoresearchindex 参数。
我们可以通过与令牌相关的方法很容易地看到这一点:搜索索引结果 将是一个btree集合,而如果没有搜索索引,则结果将是 发电机。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...06
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...07
我们可以看到其他方法接受这个参数,但是结果看起来 与往常一样。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...08
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...09
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...10
findrelationtokens()
如果在没有任何参数的情况下调用findrelationtokens,您将得到 目录中所有关系标记的树集。这对测试很方便 以及目录的高级使用。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...11
FindValueTokens(索引名)
如果只使用索引名调用findValueTokens,将得到btree 索引中该值的所有标记的结构。这很方便 测试和目录的高级使用。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...12
结论
回顾
这就结束了我们的介绍我举个例子。让我们回顾一下 然后看看你可以从这里走到哪里。
关系是具有索引值的对象。
关系目录索引关系。这种关系可以是单向的, 双向、三向或N向,只要告诉目录为 不同的值。
创建目录:
< Buff行情>关系及其值作为标记存储在目录中:唯一 可以解析回原始值的标识符。整数是 最有效的代币,但其他代币也可以正常工作。
令牌类型决定所需的btree模块。
< Buff行情>- 如果令牌是32位整数,请选择 btrees.family32.ii , btrees.family32.if 或 btrees.family32.io
- 如果令牌是64位整数,请选择 btrees.family64.ii , btrees.family64.if 或 btrees.family64.io
- 如果它们是其他的,请选择btrees.family32.oi, btrees.family64.oi 或 btrees.family32.oo (或 btrees.family64.oo–它们是相同的。
在这些规则中,选择有些武断,除非您计划 将这些结果与使用 特定的btree模块。btree set操作只在同一个 模块,因此您必须将模块与模块匹配。
在实例化catalog中的 family 参数允许您更改 关系和值索引的默认btree系列 btrees.family32.if 到 btrees.family64.if
必须定义自己的标记化和解析标记的函数。 这些函数在关系和 它们的每个值索引。
您可以向关系目录添加值索引,以便能够进行搜索。价值观 可通过可调用项或接口元素标识到目录。
< Buff行情>- 使用接口属性将导致尝试调整 如果尚未提供接口,则为关系。
- 在将值索引定义为 指示索引值是集合。默认为 错误。
- 在将值索引定义为 指定要在查询中使用的名称,而不是依赖于 接口属性或可调用的名称。
您可以设置搜索索引来加速特定的搜索,通常 可传递。
侦听器可以在目录中注册。当 关系被添加、修改或删除;当目录被清除时 并复制。
目录管理:
< Buff行情>- 关系用索引(关系)索引,并从 目录中有 未索引(关系) 。 索引文档(关系令牌, 关系) 和 取消索引文档(关系令牌) 也可以工作。
- clear方法清除目录中的关系。
- copy方法通过复制来复制当前目录 内部数据结构,而不是重新索引关系,这可以 成为一个重要的优化机会。这将复制值索引和 搜索索引;并使侦听器有机会指定 任何内容,都应包含在新副本中。
搜索目录:
< Buff行情>对关系目录的查询由dict组成。
查询键是要搜索的索引的名称,或者 精确关系的特殊情况,即 zc.relation.relation 常数。
查询值是要匹配的结果的标记;或者 无 ,表示将 无 作为值(或空)的关系 集合(如果是倍数)。搜索值可以使用 zc.关系catlog.any(args) 或 zc.relation.catalog.any(args) 到 指定多个(non- none )结果以匹配给定的密钥。
索引有多种方法可帮助您使用标记。 tokenizequery 通常是最常用的,尽管其他的是 可用。
要查找与查询匹配的关系,请使用 findRelations 或 FindRelationtokens 。调用不带任何 参数返回目录中所有关系标记的树集。
要查找与查询匹配的值,请使用 findValues 或 findValueTokens 。仅使用名称调用findValueTokens 返回目录中所有令牌的btree集 价值指数。
您可以使用查询工厂进行传递性搜索。这个 zc.relation.queryfactory.transportingtransitive 是一个很好的常见情况 允许您在层次结构中上下移动的工厂。查询工厂可以 作为搜索方法的参数作为queryfactory传入,或 作为默认行为安装,使用 addDefaultQueryFactory
要查找查询的关联方式,请使用 findRelationChains 或 FindRelationtokenchains
要确定查询是否相关,请使用 canfind
循环传递关系被处理以防止无限循环。他们 在 findrelationchains 和 findrelationtokenchains 中确定 带有一个 zc.relation.interfaces.icircularrelationpath 标记接口。
搜索方法共享以下参数:
- 最大深度 ,限制搜索的传递深度;
- 过滤,允许代码过滤可传递路径;
- targetquery ,允许查询筛选 端点的基础;
- targetfilter ,允许代码根据 终点;和
- 上述queryfactory 。
此外, findRelations 的 ignoresearchindex 参数, FindRelationTokens , FindValues , FindValues标记 ,以及 canfind导致搜索忽略搜索索引,即使存在 一个合适的。
下一步
如果你想读更多的书,接下来的步骤取决于你喜欢怎样学习。在这里 是zc.relation包中的一些其他文档。
<表> < COL/> < COL/> <正文>最后,真正的死难者也可能对时间感兴趣 目录,其中包含用于测试假设和学习的脚本。
[12] | 如果你想,看看当你去 其他方式: >>> catalog._attrs = dict(catalog._attrs)8 >>> catalog._attrs = dict(catalog._attrs)9 >>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...0 >>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...1 >>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...2 >>> def supervisor(emp, catalog): ... return emp.supervisor # None or another employee ...3 |
优化。rst: | |
---|---|
优化关系目录使用的最佳实践。 | |
搜索索引。rst: | |
查询工厂和搜索索引:从基础到细节。 | |
令牌。rst: | 本文档探索令牌的详细信息。全神的辣椒 爱情信物,至少如果上帝的奇伦在写非玩具应用程序 使用zc.relation。它包括对令牌助手的讨论 目录提供了如何使用zope.app.intid-like注册表 关系,如何使用令牌合理地"连接"查询结果 以及如何索引连接。这也是不必要的 因为所用的例子,令人心驰神往。 |
接口。py: | 螺母和螺栓的合同。 |
标记和联接:zc.关系目录扩展示例
介绍和设置
本文档假设您已经阅读了介绍性的readme.rst并希望 以身作则。在它中,我们将探索 一组复杂的关系,展示了 使用代币。特别是,我们将研究连接,它将 也让我们有机会更深入地了解查询工厂和 搜索索引,并引入侦听器的思想。它无法解释 自述文件中已经提到的基础知识。
假设我们正在为系统中的安全断言编制索引。在这 系统中,用户可能在组织中具有角色。各组织 可能有多个子组织,也可能只有一个父组织 组织。在父组织中具有角色的用户将具有 在所有传递连接的子关系中扮演相同的角色。
我们有两种关系。一种关系将模型 组织的等级制度。我们用一个内在的关系 组织对孩子的影响:这反映了一个事实 组织选择并由他们的孩子组成;孩子选择 不要选择父母。
另一个关系将为(单个)用户具有的(多个)角色建模 在一个(单一)组织中。这种关系完全是外在的。
我们可以创建两个目录,每种类型一个。或者我们可以把它们 都在同一个目录中。最初,我们将使用单个目录 我们的例子。那么,这个目录将为 关系的异构集合。
让我们用接口定义这两种关系。我们将包括一个 访问器,getorganization,主要用于显示如何处理方法。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...13
现在我们可以创建一些类。在自述示例中,设置有点 玩具的这次我们会更实际一点。我们也会期待 在zodb中操作,有根和事务。 [14]
[13] | 好的,您关心查询工厂是如何工作的,所以 我们会调查一下的。让我们通过两个步骤来讨论 第二个问题中的传递搜索。最初的目录 执行请求的初始不及物搜索:查找关系 贝蒂是他们的主管。那是黛安娜和埃德加。 现在,对于每个结果,目录都要求查询工厂 下一步。我们带黛安娜去吧。目录对工厂说, "考虑到贝蒂是主管的关系问题,我得到了 这是黛安娜的结果。你还有其他问题要问吗 再往前看?"。工厂还获取目录实例,因此 如果需要,可以用它来回答问题。 好吧,下一部分是你的大脑受伤的地方。坚持住, 在我们的例子中,工厂看到查询是针对主管的。它的 另一个键,它所转换的键是 zc.relation.relation 。< EM > factory获取当前令牌的转置密钥结果。so,for us, zc.relation.relation 的一个键实际上是一个no op:结果 是 现在的代币,黛安娜。然后,工厂有了自己的答案:更换旧的 查询中的supervisor值betty,结果为diane。下一个 传递查询应该是{'supervisor','diane'}。TA D. < /P> |
我们将如何转储和加载关系:使用"注册表" 对象,类似于intid实用程序。 [15]
[14] | 这里我们将设置一个zodb实例供我们使用。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...14 |
在这个"dump"方法的实现中,我们使用缓存来 告诉你如何使用它。这工作可能有点过分了, 甚至可能会失去速度,但你可以看到这个想法。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...18
现在我们可以创建一个关系目录来保存这些项目。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...19
现在我们建立索引。我们从组织开始,然后 用它们建立目录。这部分将类似于示例 在readme.rst中,但是将引入更多关于优化和 令牌。然后我们将添加关于角色的部分,并探索查询和 基于令牌的"连接"。
组织
组织将拥有一组组织。这实际上不是 在zodb中本来就很容易,因为这意味着我们需要比较 或者散列持久对象,这些对象随着时间的推移不能可靠地工作,并且 把机器从盒子里拿出来。为了回避这个例子的问题, 还是做一些有点意思的真实的事情,我们会用 上面介绍的注册表标记。这也会给我们一个机会 再多谈谈优化和令牌。(如果你愿意 要以理智和透明的方式保存一组持久对象,请尝试 尚未设置包xxx。)
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...20
好的,现在我们知道组织将如何运作。现在我们可以添加 部分 目录索引。这将从我们添加的 自述文件中的索引。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...21
那么,与自述示例有什么不同?
首先,我们使用一个接口元素来定义要索引的值。 它提供了一个接口,对象将被适应,一个默认名称 对于索引,以及有关是否应使用该属性的信息 直接或致电。
其次,我们没有指定转储或加载。他们没有。这个 意味着索引值已被视为标记。这个 如果索引为 值是使用与 索引–这将引出下一个差异。
第三,我们指定 multiple=true 。这意味着 在一个给定的关系上,提供或能够适应组织将 收集 部分。这些永远都是一套, 实际colection是btrees集还是btree的键。
最后,我们指定一个用于查询的名称。我发现这些疑问 当查询键是单数时更容易阅读,因此我经常重命名复数。
在自述文件中,我们可以添加另一个简单的转置传递查询 工厂,在"部分"和"无"之间切换 < Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...22
让我们在查找的层次结构中添加几个搜索索引…
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...23
…向下。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...24
请注意:搜索索引实际上不是一个好主意。这个 索引是为向下查找而设计的。
[15] | 这里有一个简单的持久密钥引用。注意它是 不是持久的:这对解决冲突很重要 能够工作(我们在这里没有展示,但我们试着靠得更多 走向实用对于本例)。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...15 这是一个简单的整数标识符工具。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...16 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...17 |
让我们创建并添加一些组织。
我们将创建这样的结构
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...26
这是蟒蛇。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...27
现在目录知道了这些关系。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...28
而且,现在我们可以搜索了。为此,我们可以使用一些 T他提供目录。最常用的是tokenizequaly。它需要一个 使用未标记化的值进行查询并将其转换为 标记化。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...29
当然,现在单独用"part"做这个有点傻,因为 不会在关系目录中更改(因为我们说过dump和 负荷 无 ,如上所述。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...30
tokenizequery方法非常常见,我们将把它分配给 我们例子中的变量。然后我们将进行一两次搜索。
所以…找出YNOD开发人员管理的关系。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...31
好吧…我们使用了findrelationtokens,而不是findrelations,所以 现在是几个数字。我们如何将它们转换回来? ResolveRelationTokens 将起作用。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...32
resolvequery 是tokenizequaly的镜像:它转换 标记化查询到具有"加载"值的查询。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...33
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...34
同样, tokenizerelations 是 resolvereationtokens 的镜像。 < Buff行情>
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...35
其他与令牌相关的方法如下 [17] :
[16] | transmissingTransitiveMembership索引 提供ISearchindex。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...25 |
- tokenizevalues ,它返回值的一个iterable标记 给定索引名的;
- resolveValueTokens ,它返回 给定的索引名;
- 标记化 ,返回给定关系的标记;和
- ResolveRelationToken ,它返回给定令牌的关系。
为什么我们要用这些代币,而不是把它们藏起来 使api更漂亮?通过曝光它们,我们可以实现高效的连接, 以及在其他情况下的有效使用。例如,如果您使用相同的 intid实用程序在其他目录中标记,我们的结果可以合并 其他目录的结果。同样,您可以使用结果 对其他目录的查询-甚至从 正在查询此目录-作为此处的查询值。我们将在 下一节。
角色
我们已经建立了组织关系。现在让我们设置角色,然后 实际上能够回答我们在开头描述的问题 文件的。
在我们的roles对象中,roles和principal只是字符串–id,如果 这是一个真正的系统。组织将是直接的对象引用。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...40
现在,让我们将值索引添加到关系目录中。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...41
这些是我们在 addvalueindex 以前,但所有的混合和匹配相同的成分。
提醒一下,我们的组织结构如下:
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...26
现在,让我们创建并添加一些角色。
< Buff行情> αααα143现在,我们可以开始进行搜索了。
[17] | 对于它的价值,这里有一些小的 其余令牌相关方法的示例。 这两个是 tokenizerelations 和 解决关系令牌 标记化 返回给定关系的标记。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...36 ResolveRelationToken 返回给定令牌的关系。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...37 现在"价值观"的表现有点蹩脚,因为唯一的价值观 我们现在没有标记化,而是直接使用。但是这里 去,显示一些迷人的禁止操作。 tokenizevalues ,返回 给定的索引名。 αααα138resolveValueTokens 返回 给定的索引名。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...39 |
奥菲莉亚的角色设置是什么?
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...45
这个答案不需要传递:我们完成了。
下一个问题。奥菲莉亚在哪里扮演"作家"的角色?
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...46
好吧,这是不及物的。我们需要传递查询吗 工厂?不!这是一个很好的机会来看看我们谈过的 关于上一节。这实际上应该是两个步骤 行动:找到所有奥菲莉亚有作家的组织, 然后找到该组织的所有可传递部分。
< Buff行情> αααα147更像是这样。
下一个问题。哪些用户在"zookd devs"组织中有角色? 不及时性,这很容易。
< Buff行情> αααα148在传递性方面,我们应该执行另一个连接。
< Buff行情> αααα149这有点尴尬,但它确实起到了作用。
< dl >奥菲莉亚在"Zookd NBD"组织中扮演什么角色?
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...50
不及时性,这是正确的。但是,从传递的角度来说,奥菲莉亚也有 评论员和作者,这是我们希望能够快速得到的答案。
我们可以用另一种方式来提问,然后,再次利用join。 我们将它设置为一个函数,因为我们稍后将要使用它 不重复代码。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...51
如您所见,使用令牌使有趣的连接成为可能, 只要两个查询中的标记相同。
我们已经研究了标记方法和标记技术,比如连接。实例 我们讲的故事可以让我们进入一些更高级的话题,比如 查询工厂连接并搜索可以提高读取速度的索引。
查询工厂连接
我们可以建立一个查询工厂,使连接自动进行。查询 factory是一个带两个参数的可调用函数:一个查询 开始搜索)和目录。工厂要么不退货, 指示查询工厂不能用于此查询,或 返回另一个接受关系链的可调用函数。最后 关系链中的令牌是最新的。这个的输出 内部可调用的 btrees.family32.oo.bucket查询以从给定链进一步搜索 关系的。
这是解决这个问题的一个有缺陷的方法。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...52
这对我们当前的示例有效。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...53
但是,对于其他类似的查询,它将不起作用。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...54
有缺陷的工厂实际上是更典型的关系的有用模式 遍历。从一种关系到另一种关系,奥菲莉亚 一直到高层都有联系。然而,安倍只有 顶部,因此没有任何东西被遍历。
相反,我们可以创建一个查询工厂来修改初始查询。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...55
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...56
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...57
这种方法和另一种方法的区别在于 不及物的:这个查询工厂修改初始查询,然后 不要再问了。目录当前总是停止调用 如果查询不返回任何结果,因此 有缺陷的工厂根本无法解决此类问题。
我们可以将此查询工厂添加为另一个默认值。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...58
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...59
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...60
以前安装的查询工厂仍然可用。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...61
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...62
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...63
查询工厂联接的搜索索引
现在我们已经编写了一个封装连接的查询工厂,我们可以 使用加快搜索速度的搜索索引。我们只使用传递搜索 迄今为止的索引。现在我们将添加一个不及物搜索索引。
不及物搜索索引通常只需要搜索值 名称应该是索引,结果名称(默认为 关系),并且可以选择要使用的查询工厂。
我们需要使用两个额外的选项,因为我们是 做。我们需要指定组织和主体id值需要什么 当对象被索引时被更改,并且我们需要指出 应在组织、负责人id、 或 部件更改时更新。
getvaluetokens 指定需要索引的值。它得到 索引、所需令牌的名称、令牌、目录 生成了令牌更改(它可能与索引的 catalog,包含值字典的源字典 如果不重写标记,则将用于标记 此标记的附加值(键是值名),是 已删除此标记的值,以及是否已删除该标记。 方法不能返回none,这将使索引保留为默认值 在没有使用查询工厂的情况下应该有效的行为;或者 值:
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...64
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...65
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...66
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...67
[18] | 我们还可以更多地显示值标记方法 现在清醒。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...44 |
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...68 < > <表>
现在我们可以改变和消除关系,包括组织和角色 使索引保持正确状态。考虑到 组织–
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...26
–首先,我们将把ynod dev移到zookd dev下面,然后退出。本遗嘱 简要地给予Y3L4项目和其他项目ABE完全特权。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...70
作为另一个例子,我们将改变安倍的角色,并看到它是 向下传播到zookd nbd。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...71
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...72
请注意,搜索索引顺序很重要。在我们的例子中,我们的不及物搜索 索引依赖于我们的传递索引,因此传递索引需要 先来。在名称之前需要可传递关系索引。马上, 你负责这个订单,很难想出一个 可靠的猜测算法。
侦听器、目录管理和跨关系目录加入
到目前为止,我们已经用一个索引目录完成了所有示例 两种关系。如果我们想要两个目录 同质的关系集合?感觉很干净,但也很干净 引入一些新的皱纹。
让我们使用当前的组织目录,删除多余的 信息;并为角色创建一个新角色。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...73
我们需要一个稍微不同的查询工厂和一个稍微不同的 搜索索引 getvaluetokens 函数。我们将编写这些,然后修改 为新世界配置两个目录。
我们在这里编写的可传递工厂用于角色目录。资讯科技成功 访问组织目录。我们可以做很多 方法-依赖实用程序,或从上下文中查找目录。我们将 使角色目录具有.org目录属性,并依赖该属性。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...74
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...75
如果你在代码中跟随并与原件进行比较,你可以 要知道,这种方法比关系 在同一目录中。
现在我们将修复组织目录
这还显示了如何使用RemoveDefaultQueryFactory和RemoveSearchIndex 方法
[20] | 在我们修改它们之前,让我们看看我们制作的副本。 副本当前的行为应与原件相同。 αααα176>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...77 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...78 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...79 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...80 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...81 αααα182 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...83 |
现在我们将设置角色目录
[21] | 通过删除查询会得到错误 未注册的工厂。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...84 |
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...85
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...86
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...87
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...88 < > <表>
新的角色目录索引需要从组织目录更新。 我们将使用侦听器来设置,这是一个新概念。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...89
现在角色目录应该能够回答与旧目录相同的问题 单一目录法。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...90
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...91
我们还可以对目录和搜索索引进行更改 维护。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...92 αααα193
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...94
我们在这里添加一个新组织。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...95
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...96
>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...97
现在我们将删除它。
< Buff行情>>>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...98
要确保不及物复制看起来与我们期望的一样
[23] | 您可以多次添加侦听器。 >>> employees = {} # we'll use this to resolve the "name" tokens >>> from functools import total_ordering >>> @total_ordering ... class Employee(object): ... def __init__(self, name, supervisor=None): ... if name in employees: ... raise ValueError('employee with same name already exists') ... self.name = name # expect this to be readonly ... self.supervisor = supervisor ... employees[name] = self ... # the next parts just make the tests prettier ... def __repr__(self): ... return '<Employee instance "' + self.name + '">' ... def __lt__(self, other): ... return self.name < other.name ... def __eq__(self, other): ... return self is other ... def __hash__(self): ... ''' Dummy method needed because we defined __eq__ ... ''' ... return 1 ...99 现在,我们将删除侦听器,以显示我们的能力。 >>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...00 删除我们没有的搜索索引也一样 >>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...01 |
使用搜索索引:zc.relation catalog扩展示例
简介
本文档假设您已经阅读了readme.rst文档,并希望了解 再举个例子。在书中,我们将探讨一组关系 演示使用搜索索引和侦听器的大多数方面。 它不会解释其他文件已经涉及的主题。它 还描述了一个高级用例。
正如我们在其他文档中看到的,关系目录支持 搜索索引。它们可以根据需要返回任何搜索的结果。 当然,其目的是提供一个索引来优化 它声称的特定搜索。
searchindex模块提供一些搜索索引,优化 指定传递和不传递搜索。我们看到他们在工作 在其他文件中。我们将在本文档中对它们进行更深入的研究。
搜索索引通过"侦听器"接收消息来更新自身 接口。我们还将了解它的工作原理。
此文件中描述的示例检查类似于 zc.revision或zc.vault包:关系描述了 其他物体。因此,这是我们第一个 外部关系。
让我们建立一个例子故事一点。假设我们有一个图表,通常是 标记的层次结构-整数。关系指定给定的整数 令牌与其他整数令牌相关,包含表示或 其他含义。
整数还可以具有指定它们表示 一个或多个对象。
这允许我们有一个对象图,其中更改 图表不需要更改其余部分。因此,zc.revision和zc.vault 能够有效地为具有多个修订的图建模 有相当多的元数据支持合并。
让我们想象一个简单的层次结构。关系具有 标记 属性 还有一个 children 属性;children指向标记。关系会 用身份证证明自己。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...02 αααα203
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...04
标准TransportingTransitioneQueriesFactory将能够处理此问题 很好,所以我们用它作为索引。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...05
现在,让我们快速创建一个层次结构并将其索引。
< Buff行情> αααα206[25] 该层次结构是任意的。以下是我们的代币 指向子对象:
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...07
12个关系,标记0到11,总共33个标记, 包括孩子们。12个关系的id是100到111, 对应于0到11的标记。
没有可传递的搜索索引,我们可以得到所有可传递的结果。 结果是迭代器。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...08 αααα209
[26] 也可以进行转换,并且将 使用可传递的搜索索引,如下所示。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...10
FindRelationtokenChains 不会改变,但我们会将其包含在 讨论和示例来说明这一点。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...11
可传递的搜索索引
现在我们可以添加几个传递搜索索引。我们来谈谈 先说一点。
目前有一种传递索引,它将 转换传递查询的关系和值搜索 工厂。
索引只能在特定条件下使用。
< Buff行情>- 搜索不是对关系链的请求。
- 它没有指定最大深度。
- 不使用过滤器。
如果是值搜索,则在 使用目标筛选器或目标查询,但基本关系索引可以 在这种情况下仍然使用。
搜索索引的使用在很大程度上是透明的:设置它们,以及 关系目录将它们用于使用更多 以前是蛮力。与外部用途的唯一区别是 使用索引的结果通常是btree结构,而不是 迭代器。
为关系添加可传递索引时,必须指定 查询的可传递名称(或名称),反之亦然。 这就是我们现在要做的一切。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...12
现在我们应该安装一个搜索索引。
注意我们是从父母那里(托克n)对儿童:该指数主要是 旨在帮助在层次结构中传递成员身份搜索。用它来 索引父项将为不太成功而招致大量写开销。
您可以在这里指定更多内容:查询的静态字段 做一些过滤。在这个例子中,我们不需要这些。
现在,目录如何使用此索引进行搜索?三种基本方式, 根据搜索的类型、关系、值或 canfind 。 在我们开始调查内部结构之前,让我们验证一下 我们期望的是:正确的答案,而不是迭代器,而是树结构。
< Buff行情> αααα213>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...14
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...15
[27] 注意,最后两个 可以从 当我们浏览这些没有索引的示例时,不要使用 索引,所以我们不在这里显示它们:它们看起来方向不对 此索引。
那么这些结果是如何发生的呢?
第一个, findrelationtokens 和最后一个, canfind 是最多的 直截了当。索引查找与给定的 查询,不及时性。然后为每个关系查找索引 该标记的传递结果。最终的结果是所有人的联合 从不及物搜索中找到的索引结果。 可以找到 将结果转换为布尔值。
findValueTokens 与上面的相同,只需再多做一步。后 计算关系的并集,该方法返回 为所有找到的关系设置请求的值。
当关系重新建立索引时,它将保持自身。
< Buff行情> αααα216>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...17
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...18 αααα219
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...20
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...21
复制索引时,将复制搜索索引。
< Buff行情> αααα222帮助程序
在编写搜索索引和查询工厂时,通常需要完成 访问关系目录数据。我们已经看到许多这样的工具:
getrelationmoduletools 获取所需btree工具的字典 处理关系。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
23只有当btree是i*或l*模块时,"multiunion"才存在。 使用zc.relation.catalog.multiunion助手函数执行 对于给定的工具集,您可以进行最佳组合。
getvaluemoduletools 对索引值也一样。
< Buff行情> αααα224>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
25getrelationtokens 可以返回目录中的所有令牌。
< Buff行情> αααα226这也恰好相当于一个空的 查询,
αααα227它还可以返回与给定查询匹配的所有标记,如果 没有匹配项。
αααα228这也恰好相当于查询的 findrelationtokens , 最大深度为1,没有其他参数。
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
29除非没有匹配项, findrelationtokens 返回一个空 set(因此它总是返回iterable)。
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
30- getvaluetokens 可以返回中给定值名称的所有令牌
目录。
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
31这与仅具有名称(或 空查询,最大深度为1)。
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
32它还可以返回给定令牌的值。
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
33这与catalog.findValueTokens相同,后者具有名称和查询 {无:标记}。
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
34除非没有匹配项, findValueTokens 返回一个空 set(因此它总是返回iterable);而getvaluetokens将 如果关系没有值(或关系未知),则返回none。
αααα235>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...
36查询工厂。待办事项:描述。
[24] | 在《2001:太空漫游》中,许多人相信哈尔这个名字 被选中是因为它是IBM的Rot25…我有时会作弊 使用rot1,因为结果听起来更好。 |
[25] | 查询工厂知道何时不需要它–不仅如此 当它的两个名字都没有被使用,而且当它的两个名字都是 使用。 >>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...37 |
<当值与它们的令牌相同时,
findValues
返回与
findValueTokens
相同的结果。在这里
我们看到这个没有索引。
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...38 |
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...38 < > <表>
优化关系目录的使用
在以下方面有一些最佳实践和优化机会 目录。
- 尽可能使用带整数键的btree集。他们可以用树 多联合 以提高速度。整数cmp是可靠的,在c中。
- 永远不要使用持久对象作为键。它们将导致 当您需要查看它们时,它们占用内存和对象缓存,并且 他们(截至本文撰写时)禁用冲突解决。Intids(或类似) 是表示对象的最佳选择,以及一些其他不可变的,如 字符串是下一个最佳匹配,zope.app.keyreferences(或类似的)是 之后。
- 尽可能在查询中使用多个标记值,特别是在 传递查询工厂。
- 在加载和转储令牌时使用缓存,并在 传递查询工厂。
- 如果可能,不要加载或转储令牌(可以使用值本身 作为标记)。当您有多个令牌时,这一点尤其重要: 将它们存储在与zc.relation模块相同的模块中的btree结构中。 价值。
对于某些操作,特别是在 单个关系值,其中一些优化可以加快 常见情况下,重新编制索引的工作次数约为100次。
最简单(也可能最不有用)的优化是 单个操作生成的调用和所有加载调用共享一个缓存 每个调用类型的字典(转储/加载),每个索引关系值。 因此,例如,我们可以保存intids实用程序,以便 只需执行一次实用程序查找,此后它只 单字典查找。这是默认的 generatetoken 和 resolvetoken 函数在zc.relationship的index.py do中:查看它们 例如。
进一步的优化是根本不加载或转储令牌,而是使用值 那可能是代币。如果令牌具有 _ c语言中的cmp_uuu(或等效的),如ints之类的内置类型。指定 此行为将创建一个索引,其中包含 索引属性描述显式设置为"无"。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...40
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...41
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...42
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...04
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...44
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...45
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...46
如果你有成百上千的关系 对象,如果值是相同的"倍数",则可能是一个巨大的胜利 键入作为给定属性的存储btree。默认btree 属性的族是ifbtree;iobtree也是一个不错的选择,并且可以 在某些应用中更受欢迎。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...47
重新编制索引是可以实现一些重大改进的地方。以下 回转操作优化代码。
BLOCKQuo>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...48
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...49
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...50
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...51
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...52
>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...53
TokenIzeValues和ResolveValueTokens在没有加载程序和 翻车机-也就是说,它们什么也不做。
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...54
更改
1.1.post2(2018-06-18)
- 另一次尝试使用正确的预期元数据语法修复PYPI页。
1.1.post1(2018-06-18)
- 使用正确的rest语法修复pypi页面。
1.1(2018-06-15)
- 添加对Python3.5和3.6的支持。
1.0(2008-04-23)
这是zc.relation包的初始版本。然而,它 表示另一个包zc.relationship的重构。这个 包仅包含关系(发货)索引的修改版本, 现在称为目录。zc.relationship索引的重构版本 依赖于(子类)此目录。ZC.关系也保持 向后兼容的子类。
这个包只依赖于zodb、zope.interface和zope.testing 软件,可以在标准zodb数据库内部或外部使用。 不过,软件必须在那里(软件包非常依赖 在zodb btrees包中)。
如果要将旧的zc.relationship索引切换到 关系目录,在你的generations脚本中试试这个技巧。 假设旧索引是 旧的 ,则应创建以下行 一个新的zc.relation目录,包含您的旧数据:
< Buff行情>>>> def dumpEmployees(emp, catalog, cache): ... return emp.name ...55
为什么相同的基本数据结构现在称为目录?因为我们 暴露了改变数据结构的能力,以及 添加和删除是索引。把索引放进去是没有意义的 索引,但将索引放入目录中确实有意义。因此,A 更名诞生。
这个包中的目录与前面的有几个不兼容 关系索引和许多新特性。zc.relationship包 维护向后兼容的子类。以下讨论 将zc.relation目录与zc.relationship 1.x索引进行比较。
与zc.relationship 1.x索引不兼容
两大变化是方法名现在引用的是 关系 而目录的实例化方式略有不同 从索引中。其他一些变化值得你注意。这个 下面的列表试图突出显示所有不兼容项。
<表> < COL/> < COL/> <正文>
更改和新功能
-
目录现在提供了索引
搜索。索引必须显式实例化和注册
你想优化。当搜索值时,当
搜索关系,或确定两个对象是否
链接的。它不能用于关系链。请求索引
通常需要权衡更大的存储空间和更慢的写入速度
加快搜索速度。注册搜索索引已完成
在实例化时间之后;您可以迭代当前设置
使用,并移除它们。(代码路径希望支持遗留的
所有这些api的关系索引实例。)
-
现在可以在创建目录后指定新值,重复
超过所使用的设置,然后删除值。
-
目录有一个复制方法,可以在没有实际操作的情况下快速创建新的副本
必须重新建立关系索引。
-
查询参数现在可以通过
使用zc.relation.catalog.any(1、2、3、4)或
zc.relation.catalog.any((1,2,3,4))。
-
目录支持通过传递callables而不是
接口元素(仍受支持)。
-
findrelations
和新方法
findrelationtokens
可以找到
传递和不传递的关系。
芬兰
当以非及时性方式使用时,重复旧的zc.relationship索引
findrelationtokenset的行为。
(
findrelationtokenset
保留在api中,而不是弃用
要
findValueTokenSet
)
-
在findValues和findValueTokens中,
query
参数现在是可选的。如果
在布尔上下文、所有值或值中,查询的计算结果为false
返回标记。值标记使用
基础btree存储。然后可以直接用于其他btree
操作。
-
全新的文档。不幸的是,仍然不够好。
-
该软件包大大减少了ZC的直接依赖关系。
它现在更明显是一个zodb工具,除了
zope.testing和zope.interface。
-
侦听器允许对象侦听来自目录的消息(可以
直接使用,或用于触发事件。
-
您可以使用zc.relation.relation…键来搜索关系。
真的没有别名。对不起的。但是嘿,用常量!我想是的
更具可读性。
-
tokenizequery(和resolvequery)现在接受关键字参数作为
普通dict查询的替代方法。这可以使构造查询
更吸引人一点(即,
query=catalog.tokenizequery;
res=
catalog.findValues('object',
查询(subject=joe,predicate=owns))
)。
大不相容性: | |
---|---|
| |
中等: |
|
小: |
|