use catalog's apply() method for querying (instead of searchResults()) - do not loose score (weight) information
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2547 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
21743d6e52
commit
a0b8e4f39b
2 changed files with 41 additions and 32 deletions
35
query.py
35
query.py
|
@ -22,9 +22,12 @@ Query management stuff.
|
|||
$Id$
|
||||
"""
|
||||
|
||||
from BTrees.IOBTree import IOBTree
|
||||
from BTrees.IFBTree import weightedIntersection, weightedUnion, IFBucket
|
||||
from zope import schema, component
|
||||
from zope.interface import Interface, Attribute, implements
|
||||
from zope.app.catalog.interfaces import ICatalog
|
||||
from zope.app.intid.interfaces import IIntIds
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
|
||||
from cybertools.typology.interfaces import IType
|
||||
|
@ -37,6 +40,16 @@ from loops import util
|
|||
from loops.util import _
|
||||
|
||||
|
||||
class ScoredSet(set):
|
||||
|
||||
def __init__(self, data=set(), scores={}):
|
||||
super(ScoredSet, self).__init__(data)
|
||||
self.scores = scores
|
||||
|
||||
def getScore(self, obj):
|
||||
return self.scores.get(obj, -1)
|
||||
|
||||
|
||||
class IQuery(Interface):
|
||||
""" The basic query interface.
|
||||
"""
|
||||
|
@ -112,10 +125,12 @@ class FullQuery(BaseQuery):
|
|||
def query(self, text=None, type=None, useTitle=True, useFull=False,
|
||||
conceptTitle=None, conceptUid=None, conceptType=None, **kw):
|
||||
result = set()
|
||||
scores = {}
|
||||
intids = component.getUtility(IIntIds)
|
||||
rc = self.queryConceptsWithChildren(title=conceptTitle, uid=conceptUid,
|
||||
type=conceptType)
|
||||
if not rc and not text and '*' in type: # there should be some sort of selection...
|
||||
return result
|
||||
return ScoredSet(result, scores)
|
||||
if text or type != 'loops:*': # TODO: this may be highly inefficient!
|
||||
cat = self.catalog
|
||||
if type.endswith('*'):
|
||||
|
@ -126,13 +141,21 @@ class FullQuery(BaseQuery):
|
|||
criteria = {'loops_type': (start, end),}
|
||||
if useFull and text:
|
||||
criteria['loops_text'] = text
|
||||
r1 = set(cat.searchResults(**criteria))
|
||||
r1 = cat.apply(criteria) #r1 = set(cat.searchResults(**criteria))
|
||||
else:
|
||||
r1 = set()
|
||||
r1 = IFBucket() #r1 = set()
|
||||
if useTitle and text:
|
||||
if 'loops_text' in criteria:
|
||||
del criteria['loops_text']
|
||||
criteria['loops_title'] = text
|
||||
r2 = set(cat.searchResults(**criteria))
|
||||
result = r1.union(r2)
|
||||
r2 = cat.apply(criteria) #r2 = set(cat.searchResults(**criteria))
|
||||
else:
|
||||
r2 = IFBucket() #r2 = set()
|
||||
x, uids = weightedUnion(r1, r2) #result = r1.union(r2)
|
||||
for r, score in uids.items():
|
||||
obj = intids.getObject(r)
|
||||
result.add(obj)
|
||||
scores[obj] = score
|
||||
if rc is not None:
|
||||
if result:
|
||||
result = result.intersection(rc)
|
||||
|
@ -142,7 +165,7 @@ class FullQuery(BaseQuery):
|
|||
if r.getLoopsRoot() == self.loopsRoot
|
||||
and canListObject(r)
|
||||
and getVersion(r) == r)
|
||||
return result
|
||||
return ScoredSet(result, scores)
|
||||
|
||||
|
||||
class ConceptQuery(BaseQuery):
|
||||
|
|
|
@ -99,33 +99,17 @@ Basic (text/title) search
|
|||
The searchresults.html view, i.e. the SearchResults view class provides the
|
||||
result set of the search via its `results` property.
|
||||
|
||||
Before accessing the `results` property we have to prepare a (for testing
|
||||
purposes fairly primitive) catalog and a resource we can search for:
|
||||
|
||||
>>> from zope.app.catalog.interfaces import ICatalog
|
||||
>>> class DummyCat(object):
|
||||
... implements(ICatalog)
|
||||
... def searchResults(self, **criteria):
|
||||
... result = []
|
||||
... name = criteria.get('loops_title')
|
||||
... if name and name.endswith('*'): name = name[:-1]
|
||||
... typeToken = criteria.get('loops_type', ('resource',))
|
||||
... if name or typeToken:
|
||||
... if 'concept' in typeToken[0]:
|
||||
... if name:
|
||||
... result = concepts.get(name)
|
||||
... else:
|
||||
... tp = concepts[typeToken[0].split(':')[-1]]
|
||||
... result = list(tp.getChildren())
|
||||
... else:
|
||||
... result = resources.get(name)
|
||||
... if not result: return []
|
||||
... return type(result) is list and result or [result]
|
||||
>>> component.provideUtility(DummyCat())
|
||||
Before accessing the `results` property we have to prepare a
|
||||
resource we can search for and index it in the catalog.
|
||||
|
||||
>>> from loops.resource import Resource
|
||||
>>> rplone = resources['plone'] = Resource()
|
||||
|
||||
>>> from zope.app.catalog.interfaces import ICatalog
|
||||
>>> from loops import util
|
||||
>>> catalog = component.getUtility(ICatalog)
|
||||
>>> catalog.index_doc(int(util.getUidForObject(rplone)), rplone)
|
||||
|
||||
>>> from loops.search.browser import SearchResults
|
||||
>>> form = {'search.2.title': True, 'search.2.text': u'plone'}
|
||||
>>> request = TestRequest(form=form)
|
||||
|
@ -155,6 +139,7 @@ resource (rplone) from above to one of the topics:
|
|||
>>> cplone = concepts['plone'] = Concept(u'Plone')
|
||||
>>> for c in (czope, czope2, czope3, cplone):
|
||||
... c.conceptType = topic
|
||||
... catalog.index_doc(int(util.getUidForObject(c)), c)
|
||||
>>> czope.assignChild(czope2)
|
||||
>>> czope.assignChild(czope3)
|
||||
>>> czope2.assignChild(cplone)
|
||||
|
@ -164,7 +149,6 @@ Now we can fill our search form and execute the query; note that all concepts
|
|||
found are listed, plus all their children and all resources associated
|
||||
with them:
|
||||
|
||||
>>> from loops import util
|
||||
>>> uid = util.getUidForObject(concepts['zope'])
|
||||
>>> form = {'search.3.type': 'loops:concept:topic', 'search.3.text': uid}
|
||||
>>> request = TestRequest(form=form)
|
||||
|
@ -193,7 +177,7 @@ of the concepts' titles:
|
|||
>>> request = TestRequest(form=form)
|
||||
>>> view = Search(page, request)
|
||||
>>> view.listConcepts()
|
||||
u"{identifier: 'id', items: [{label: 'Zope (Topic)', name: 'Zope', id: '33'}]}"
|
||||
u"{identifier: 'id', items: [{label: 'Zope (Topic)', name: 'Zope', id: '34'}, {label: 'Zope 2 (Topic)', name: 'Zope 2', id: '37'}, {label: 'Zope 3 (Topic)', name: 'Zope 3', id: '39'}]}"
|
||||
|
||||
Preset Concept Types on Search Forms
|
||||
------------------------------------
|
||||
|
@ -211,7 +195,9 @@ Let's start with a new type, the customer type.
|
|||
|
||||
>>> cust1 = concepts['cust1'] = Concept(u'Zope Corporation')
|
||||
>>> cust2 = concepts['cust2'] = Concept(u'cyberconcepts')
|
||||
>>> for c in (cust1, cust2): c.conceptType = customer
|
||||
>>> for c in (cust1, cust2):
|
||||
... c.conceptType = customer
|
||||
... catalog.index_doc(int(util.getUidForObject(c)), c)
|
||||
|
||||
>>> from cybertools.typology.interfaces import IType
|
||||
>>> IType(cust1).qualifiers
|
||||
|
|
Loading…
Add table
Reference in a new issue