Souper - 基于 ZODB 的通用索引存储
项目描述
ZODB 存储大量(轻量级)数据。
利用
Souper 是一款面向程序员的工具。它提供了一个与目录中的索引集成的一体化存储。存储中的记录是通用的。如果数据在 ZODB 中是持久的可选择的,则可以在记录中存储任何数据。
Souper 可以用于任何 Python 应用程序,无论是独立使用纯 ZODB,还是与 Pyramid,Zope 或 Plone 结合使用。
使用 Souper
提供定位器
通过将 souper.interfaces.IStorageLocator 适配到某个上下文来查找 Soup。Souper 不提供任何默认定位器。因此,首先需要提供一个。假设上下文是某个持久的类似于字典的实例
>>> from zope.interface import implementer
>>> from zope.interface import Interface
>>> from zope.component import provideAdapter
>>> from souper.interfaces import IStorageLocator
>>> from souper.soup import SoupData
>>> @implementer(IStorageLocator)
... class StorageLocator(object):
...
... def __init__(self, context):
... self.context = context
...
... def storage(self, soup_name):
... if soup_name not in self.context:
... self.context[soup_name] = SoupData()
... return self.context[soup_name]
>>> provideAdapter(StorageLocator, adapts=[Interface])
因此,我们现在可以通过名称动态创建 Soup。现在通过名称获取 Soup 更加容易
>>> from souper.soup import get_soup
>>> soup = get_soup('mysoup', context)
>>> soup
<souper.soup.Soup object at 0x...>
提供目录工厂
根据您的需求,目录及其索引可能因用例而异。目录工厂负责为 Soup 创建目录。工厂是一个名为实用工具,实现 souper.interfaces.ICatalogFactory 的实用工具。实用工具的名称必须与 Soup 相同。
在这里使用 repoze.catalog,并通过使用 NodeAttributeIndexer 允许索引通过键访问记录上的数据。对于特殊情况,可以编写自定义索引器,但默认索引器在大多数情况下就足够了
>>> from souper.interfaces import ICatalogFactory
>>> from souper.soup import NodeAttributeIndexer
>>> from souper.soup import NodeTextIndexer
>>> from zope.component import provideUtility
>>> from repoze.catalog.catalog import Catalog
>>> from repoze.catalog.indexes.field import CatalogFieldIndex
>>> from repoze.catalog.indexes.text import CatalogTextIndex
>>> from repoze.catalog.indexes.keyword import CatalogKeywordIndex
>>> @implementer(ICatalogFactory)
... class MySoupCatalogFactory(object):
...
... def __call__(self, context=None):
... catalog = Catalog()
... userindexer = NodeAttributeIndexer('user')
... catalog[u'user'] = CatalogFieldIndex(userindexer)
... textindexer = NodeTextIndexer(['text', 'user')
... catalog[u'text'] = CatalogTextIndex(textindexer)
... keywordindexer = NodeAttributeIndexer('keywords')
... catalog[u'keywords'] = CatalogKeywordIndex(keywordindexer)
... return catalog
>>> provideUtility(MySoupCatalogFactory(), name="mysoup")
目录工厂仅用于 Soup 内部,但您可能希望检查它是否正常工作
>>> catalogfactory = getUtility(ICatalogFactory, name='mysoup')
>>> catalogfactory
<MySoupCatalogFactory object at 0x...>
>>> catalog = catalogfactory()
>>> sorted(catalog.items())
[(u'keywords', <repoze.catalog.indexes.keyword.CatalogKeywordIndex object at 0x...>),
(u'text', <repoze.catalog.indexes.text.CatalogTextIndex object at 0x...>),
(u'user', <repoze.catalog.indexes.field.CatalogFieldIndex object at 0x...>)]
添加记录
如上所述,souper.soup.Record 是添加到 Soup 的唯一数据类型。记录具有包含数据的属性
>>> from souper.soup import get_soup
>>> from souper.soup import Record
>>> soup = get_soup('mysoup', context)
>>> record = Record()
>>> record.attrs['user'] = 'user1'
>>> record.attrs['text'] = u'foo bar baz'
>>> record.attrs['keywords'] = [u'1', u'2', u'ü']
>>> record_id = soup.add(record)
记录可以包含其他记录。但是,为了对它们进行索引,需要自定义索引器。因此,通常包含的记录对后续显示很有价值,但不是用于搜索
>>> record['subrecord'] = Record()
>>> record['homeaddress'].attrs['zip'] = '6020'
>>> record['homeaddress'].attrs['town'] = 'Innsbruck'
>>> record['homeaddress'].attrs['country'] = 'Austria'
访问数据
即使没有查询,也可以通过 id 获取记录
>>> from souper.soup import get_soup
>>> soup = get_soup('mysoup', context)
>>> record = soup.get(record_id)
可以使用容器 BTree 利用所有记录
>>> soup.data.keys()[0] == record_id
True
查询数据
如何查询 repoze 目录有很好的文档。排序也相同。查询通过 Soup 的 query 方法(使用 repoze 目录)传递。它返回一个生成器
>>> from repoze.catalog.query import Eq
>>> [r for r in soup.query(Eq('user', 'user1'))]
[<Record object 'None' at ...>]
>>> [r for r in soup.query(Eq('user', 'nonexists'))]
[]
要获取结果集的大小,将 with_size=True 传递给查询。生成器返回的第一个项目是大小
>>> [r for r in soup.query(Eq('user', 'user1'), with_size-True)]
[1, <Record object 'None' at ...>]
为了优化大型结果集的处理,可以不获取记录,而是获取返回轻量级对象的生成器。记录在调用时获取
>>> lazy = [l for l in soup.lazy(Eq('name', 'name'))]
>>> lazy
[<souper.soup.LazyRecord object at ...>,
>>> lazy[0]()
<Record object 'None' at ...>
如果传递 with_size=True,则将大小作为生成器的第一个值传递
删除记录
要从 Soup 中删除记录,使用 Python 的 del,就像在任何字典上做的那样
>>> del soup[record]
重新索引
记录的数据更改后,需要重新索引
>>> record.attrs['user'] = 'user1'
>>> soup.reindex(records=[record])
有时可能想要重新索引所有数据。然后必须不带参数调用 reindex。这可能需要一些时间
>>> soup.reindex()
重建目录
通常在更改目录工厂后(即添加了某些索引)需要重建目录。它用目录工厂创建的新目录替换当前目录,并重新索引所有数据。这可能需要一些时间
>>> soup.rebuild()
重置(或清除)Soup
要从 Soup 中删除所有数据并清空并重建目录,请调用 clear。
注意: 所有数据都会丢失!
>>> soup.clear()
源代码
源代码存储在 GIT 分布式版本控制系统(DVCS)中,其主要分支位于 github。
我们很高兴看到许多分叉和拉取请求,以使 Souper 更加完善。
贡献者
Robert Niederreiter <rnix [at] squarewave [dot] at>
Jens W. Klein <jk [at] kleinundpartner [dot] at>
变更日志
1.1.2 (2022-12-05)
发布轮。 [rnix]
1.1.1 (2019-09-16)
清理 NodeTextIndexer(一个循环就足够了)。 [jensens]
1.1.0 (2019-03-08)
代码风格(black,isort,utf8headers)。 [jensens]
已切换到tox进行测试,builodut已不再使用。[jensens]
Python 2/3 兼容性 [agitator]
1.0.2 (2015-02-25)
修复:文本索引器中的特殊字符Unicode失败。[jensens, 2014-02-25]
1.0.1
PEP-8。[rnix, 2012-10-16]
Python 2.7 支持。[rnix, 2012-10-16]
修复文档。
1.0
使其工作 [rnix, jensens, et al]
项目详情
下载文件
下载适用于您的平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。
源分布
构建分布
souper-1.1.2.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 38a0fcf8e1d1e830895483e7d3d91a03a4c465c3855051e805d518f53aa81c9d |
|
MD5 | 1dd6003b5728bb6841af7fa70d24b698 |
|
BLAKE2b-256 | fe148d08137567531fd283569079d31f38d0e3d9880f3c3855ef71d7a5f4b152 |
souper-1.1.2-py3-none-any.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 07f8bcfc858c5d764f0fde8f62636280916c08309cf872f380417e89d9d7396e |
|
MD5 | 751ae8b5de95f87fc65bba8ec7a6554e |
|
BLAKE2b-256 | 210322dba11501592d08d43b83d3c81fb09bad776dacb9dca2ec439db41f1b71 |