[Checkins] SVN: zope.app.catalog/trunk/ Merge nadako-sorting branch.
Dan Korostelev
nadako at gmail.com
Sat Jan 3 10:36:27 EST 2009
Log message for revision 94477:
Merge nadako-sorting branch.
Changed:
U zope.app.catalog/trunk/CHANGES.txt
U zope.app.catalog/trunk/setup.py
U zope.app.catalog/trunk/src/zope/app/catalog/README.txt
U zope.app.catalog/trunk/src/zope/app/catalog/browser/configure.zcml
U zope.app.catalog/trunk/src/zope/app/catalog/catalog.py
U zope.app.catalog/trunk/src/zope/app/catalog/classes.zcml
U zope.app.catalog/trunk/src/zope/app/catalog/interfaces.py
A zope.app.catalog/trunk/src/zope/app/catalog/keyword.py
U zope.app.catalog/trunk/src/zope/app/catalog/text.py
-=-
Modified: zope.app.catalog/trunk/CHANGES.txt
===================================================================
--- zope.app.catalog/trunk/CHANGES.txt 2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/CHANGES.txt 2009-01-03 15:36:27 UTC (rev 94477)
@@ -5,8 +5,19 @@
3.6.0 (unreleased)
------------------
-- ...
+- Make TextIndex addform use default values as specified in
+ zope.app.catalog.text.ITextIndex interface. Also, change
+ "searchableText" to "getSearchableText" there, as it's the
+ right value.
+- Add Keyword (case-insensitive and case-sensitive) catalog
+ indices. It's now possible to use them, because ones in
+ zope.index now implement IIndexSearch interface.
+
+- Add support for sorting, reversing and limiting result set
+ in the ``searchResults`` method, using new IIndexSort interface
+ features of zope.index.
+
3.5.2 (2008-12-28)
------------------
Modified: zope.app.catalog/trunk/setup.py
===================================================================
--- zope.app.catalog/trunk/setup.py 2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/setup.py 2009-01-03 15:36:27 UTC (rev 94477)
@@ -69,7 +69,7 @@
'zope.app.container',
'zope.app.intid',
'zope.component',
- 'zope.index',
+ 'zope.index>=3.5.0',
'zope.interface',
'zope.lifecycleevent',
'zope.location',
Modified: zope.app.catalog/trunk/src/zope/app/catalog/README.txt
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/README.txt 2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/README.txt 2009-01-03 15:36:27 UTC (rev 94477)
@@ -22,6 +22,7 @@
... zope.interface.implements(
... zope.index.interfaces.IInjection,
... zope.index.interfaces.IIndexSearch,
+ ... zope.index.interfaces.IIndexSort,
... )
...
... def clear(self):
@@ -53,6 +54,12 @@
... if set is None:
... set = BTrees.IFBTree.IFTreeSet()
... return set
+ ...
+ ... def sort(self, docids, limit=None, reverse=False):
+ ... for i, docid in enumerate(sorted(docids, key=self.backward.get, reverse=reverse)):
+ ... yield docid
+ ... if limit and i >= (limit - 1):
+ ... break
The class implements `IInjection` to allow values to be indexed and
unindexed and `IIndexSearch` to support searching via the `apply`
@@ -227,6 +234,54 @@
>>> list(result) == [o4, o5]
True
+The searchResults method also provides a way to sort, limit and reverse
+results.
+
+When not using sorting, limiting and reversing are done by simple slicing
+and list reversing.
+
+ >>> list(cat.searchResults(size=5, _reverse=True)) == [o5, o4]
+ True
+
+ >>> list(cat.searchResults(size=5, _limit=1)) == [o4]
+ True
+
+ >>> list(cat.searchResults(size=5, _limit=1, _reverse=True)) == [o5]
+ True
+
+However, when using sorting by index, the limit and reverse parameters
+are passed to the index ``sort`` method so it can do it efficiently.
+
+Let's index more objects to work with:
+
+ >>> o7 = DiscriminatingPerson(7, 'blue')
+ >>> o8 = DiscriminatingPerson(3, 'blue')
+ >>> o9 = DiscriminatingPerson(14, 'blue')
+ >>> o10 = DiscriminatingPerson(1, 'blue')
+ >>> ids.data.update({7: o7, 8: o8, 9: o9, 10: o10})
+ >>> cat.index_doc(7, o7)
+ >>> cat.index_doc(8, o8)
+ >>> cat.index_doc(9, o9)
+ >>> cat.index_doc(10, o10)
+
+Now we can search all people who like blue, ordered by age:
+
+ >>> results = list(cat.searchResults(color='blue', _sort_index='age'))
+ >>> results == [o3, o10, o8, o7, o6, o9]
+ True
+
+ >>> results = list(cat.searchResults(color='blue', _sort_index='age', _limit=3))
+ >>> results == [o3, o10, o8]
+ True
+
+ >>> results = list(cat.searchResults(color='blue', _sort_index='age', _reverse=True))
+ >>> results == [o9, o6, o7, o8, o10, o3]
+ True
+
+ >>> results = list(cat.searchResults(color='blue', _sort_index='age', _reverse=True, _limit=4))
+ >>> results == [o9, o6, o7, o8]
+ True
+
The index example we looked at didn't provide document scores. Simple
indexes normally don't, but more complex indexes might give results
scores, according to how closely a document matches a query. Let's
Modified: zope.app.catalog/trunk/src/zope/app/catalog/browser/configure.zcml
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/browser/configure.zcml 2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/browser/configure.zcml 2009-01-03 15:36:27 UTC (rev 94477)
@@ -65,9 +65,55 @@
/>
<addform
+ name="AddKeywordIndex"
+ label="Add a keyword index"
+ schema="..interfaces.IAttributeIndex"
+ permission="zope.ManageServices"
+ content_factory="..keyword.KeywordIndex"
+ arguments="field_name"
+ keyword_arguments="interface field_callable"
+ />
+
+<addMenuItem
+ title="Keyword Index"
+ description="Index items based on sequence of keywords"
+ class="..keyword.KeywordIndex"
+ permission="zope.ManageServices"
+ view="AddKeywordIndex"
+ />
+
+<addform
+ name="AddCaseInsensitiveKeywordIndex"
+ label="Add a keyword index (case-omsensitive)"
+ schema="..interfaces.IAttributeIndex"
+ permission="zope.ManageServices"
+ content_factory="..keyword.CaseInsensitiveKeywordIndex"
+ arguments="field_name"
+ keyword_arguments="interface field_callable"
+ />
+
+<addMenuItem
+ title="Keyword Index (case-insensitive)"
+ description="Index items based on sequence of keywords"
+ class="..keyword.CaseInsensitiveKeywordIndex"
+ permission="zope.ManageServices"
+ view="AddCaseInsensitiveKeywordIndex"
+ />
+
+<schemadisplay
+ name="index.html"
+ schema="..keyword.IKeywordIndex"
+ label="Keyword Index"
+ fields="interface field_name field_callable"
+ permission="zope.ManageServices"
+ menu="zmi_views" title="Configuration"
+ />
+
+<addform
name="AddTextIndex"
label="Add a text index"
- schema="..interfaces.IAttributeIndex"
+ schema="..text.ITextIndex"
+ fields="interface field_name field_callable"
permission="zope.ManageServices"
content_factory="..text.TextIndex"
arguments="field_name"
Modified: zope.app.catalog/trunk/src/zope/app/catalog/catalog.py
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/catalog.py 2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/catalog.py 2009-01-03 15:36:27 UTC (rev 94477)
@@ -134,8 +134,23 @@
return result
def searchResults(self, **searchterms):
+ sort_index = searchterms.pop('_sort_index', None)
+ limit = searchterms.pop('_limit', None)
+ reverse = searchterms.pop('_reverse', False)
results = self.apply(searchterms)
if results is not None:
+ if sort_index is not None:
+ index = self[sort_index]
+ if not zope.index.interfaces.IIndexSort.providedBy(index):
+ raise ValueError('Index %s does not support sorting.' % sort_index)
+ results = list(index.sort(results, limit=limit, reverse=reverse))
+ else:
+ if reverse or limit:
+ results = list(results)
+ if reverse:
+ results.reverse()
+ if limit:
+ del results[limit:]
uidutil = component.getUtility(IIntIds)
results = ResultSet(results, uidutil)
return results
Modified: zope.app.catalog/trunk/src/zope/app/catalog/classes.zcml
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/classes.zcml 2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/classes.zcml 2009-01-03 15:36:27 UTC (rev 94477)
@@ -42,6 +42,19 @@
/>
</class>
+ <class class=".keyword.KeywordIndex">
+ <require
+ permission="zope.ManageServices"
+ interface=".interfaces.IAttributeIndex
+ zope.index.interfaces.IStatistics"
+ set_schema=".interfaces.IAttributeIndex"
+ />
+ </class>
+
+ <class class=".keyword.CaseInsensitiveKeywordIndex">
+ <require like_class=".keyword.KeywordIndex" />
+ </class>
+
<class class=".text.TextIndex">
<require
permission="zope.ManageServices"
Modified: zope.app.catalog/trunk/src/zope/app/catalog/interfaces.py
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/interfaces.py 2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/interfaces.py 2009-01-03 15:36:27 UTC (rev 94477)
@@ -28,9 +28,26 @@
"""Provides Catalog Queries."""
def searchResults(**kw):
- """Search on the given indexes."""
+ """Search on the given indexes.
+
+ Keyword arguments dictionary keys
+ are index names and values are queries
+ for these indexes.
+
+ Keyword arguments has some special names,
+ used by the catalog itself:
+
+ * _sort_index - The name of index to sort
+ results with. This index must implement
+ zope.index.interfaces.IIndexSort.
+ * _limit - Limit result set by this number,
+ useful when used with sorting.
+ * _reverse - Reverse result set, also
+ useful with sorting.
+ """
+
class ICatalogEdit(zope.index.interfaces.IInjection):
"""Allows one to manipulate the Catalog information."""
Copied: zope.app.catalog/trunk/src/zope/app/catalog/keyword.py (from rev 94476, zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/keyword.py)
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/keyword.py (rev 0)
+++ zope.app.catalog/trunk/src/zope/app/catalog/keyword.py 2009-01-03 15:36:27 UTC (rev 94477)
@@ -0,0 +1,39 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Keyword catalog index
+
+$Id:$
+"""
+import zope.index.keyword
+import zope.interface
+
+import zope.app.container.contained
+import zope.app.catalog.attribute
+import zope.app.catalog.interfaces
+
+class IKeywordIndex(zope.app.catalog.interfaces.IAttributeIndex,
+ zope.app.catalog.interfaces.ICatalogIndex):
+ """Interface-based catalog keyword index"""
+
+class KeywordIndex(zope.app.catalog.attribute.AttributeIndex,
+ zope.index.keyword.KeywordIndex,
+ zope.app.container.contained.Contained):
+
+ zope.interface.implements(IKeywordIndex)
+
+class CaseInsensitiveKeywordIndex(zope.app.catalog.attribute.AttributeIndex,
+ zope.index.keyword.CaseInsensitiveKeywordIndex,
+ zope.app.container.contained.Contained):
+
+ zope.interface.implements(IKeywordIndex)
Modified: zope.app.catalog/trunk/src/zope/app/catalog/text.py
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/text.py 2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/text.py 2009-01-03 15:36:27 UTC (rev 94477)
@@ -40,7 +40,7 @@
field_name = zope.schema.BytesLine(
title=_(u"Field Name"),
description=_(u"Name of the field to index"),
- default="searchableText"
+ default="getSearchableText"
)
field_callable = zope.schema.Bool(
More information about the Checkins
mailing list