Commit d9085bc3 authored by Andreas Jung's avatar Andreas Jung

Merging ajung-oneindex-multipleattributes-branch

This implements: http://lists.zope.org/pipermail/zope-coders/20002-November/002680.html
parent d9bd146e
...@@ -29,6 +29,9 @@ Zope Changes ...@@ -29,6 +29,9 @@ Zope Changes
enforce this behaviour inside the ZPublisher. See also enforce this behaviour inside the ZPublisher. See also
doc/ENVIRONMENT.txt to check with the DATETIME_FORMAT doc/ENVIRONMENT.txt to check with the DATETIME_FORMAT
- KeywordIndex and FieldIndex are now capable to index more
than one attribute of an object. This removes the ties between the
indexes ID and the attribute name to be indexed.
Bugs Fixed Bugs Fixed
......
...@@ -11,8 +11,7 @@ ...@@ -11,8 +11,7 @@
# #
############################################################################## ##############################################################################
"""$Id: DateIndex.py,v 1.9 2002/12/05 21:35:52 caseman Exp $ """$Id: DateIndex.py,v 1.10 2003/01/23 17:46:19 andreasjung Exp $ """
"""
from DateTime.DateTime import DateTime from DateTime.DateTime import DateTime
from Products.PluginIndexes import PluggableIndex from Products.PluginIndexes import PluggableIndex
......
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
############################################################################## ##############################################################################
"""Simple column indices """Simple column indices
$Id: FieldIndex.py,v 1.12 2003/01/23 17:46:21 andreasjung Exp $
$Id: FieldIndex.py,v 1.11 2002/12/05 21:35:52 caseman Exp $
""" """
from Products.PluginIndexes import PluggableIndex from Products.PluginIndexes import PluggableIndex
...@@ -44,7 +43,8 @@ class FieldIndex(UnIndex): ...@@ -44,7 +43,8 @@ class FieldIndex(UnIndex):
manage_addFieldIndexForm = DTMLFile('dtml/addFieldIndex', globals()) manage_addFieldIndexForm = DTMLFile('dtml/addFieldIndex', globals())
def manage_addFieldIndex(self, id, REQUEST=None, RESPONSE=None, URL3=None): def manage_addFieldIndex(self, id, extra=None,
REQUEST=None, RESPONSE=None, URL3=None):
"""Add a field index""" """Add a field index"""
return self.manage_addIndex(id, 'FieldIndex', extra=None, \ return self.manage_addIndex(id, 'FieldIndex', extra=extra, \
REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3) REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3)
...@@ -25,6 +25,19 @@ of object values, such as 'meta_type'. ...@@ -25,6 +25,19 @@ of object values, such as 'meta_type'.
<input type="text" name="id" size="40" /> <input type="text" name="id" size="40" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Indexed attributes
</div>
</td>
<td align="left" valign="top">
<input type="text" name="extra.indexed_attrs:record:string" size="40" />
<em>attribute1,attribute2,...</em> or leave empty
</td>
</tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-optional"> <div class="form-optional">
......
...@@ -42,7 +42,7 @@ class KeywordIndex(UnIndex): ...@@ -42,7 +42,7 @@ class KeywordIndex(UnIndex):
This should have an _apply_index that returns a relevance score This should have an _apply_index that returns a relevance score
""" """
def index_object(self, documentId, obj, threshold=None): def _index_object(self, documentId, obj, threshold=None, attr=''):
""" index an object 'obj' with integer id 'i' """ index an object 'obj' with integer id 'i'
Ideally, we've been passed a sequence of some sort that we Ideally, we've been passed a sequence of some sort that we
...@@ -55,7 +55,7 @@ class KeywordIndex(UnIndex): ...@@ -55,7 +55,7 @@ class KeywordIndex(UnIndex):
# attribute we're interested in. If the attribute is callable, # attribute we're interested in. If the attribute is callable,
# we'll do so. # we'll do so.
newKeywords = self._get_object_keywords(obj) newKeywords = self._get_object_keywords(obj, attr)
oldKeywords = self._unindex.get(documentId, None) oldKeywords = self._unindex.get(documentId, None)
...@@ -85,8 +85,8 @@ class KeywordIndex(UnIndex): ...@@ -85,8 +85,8 @@ class KeywordIndex(UnIndex):
self.insertForwardIndexEntry(kw, documentId) self.insertForwardIndexEntry(kw, documentId)
return 1 return 1
def _get_object_keywords(self,obj): def _get_object_keywords(self, obj, attr):
newKeywords = getattr(obj, self.id, ()) newKeywords = getattr(obj, attr, ())
if callable(newKeywords): if callable(newKeywords):
newKeywords = newKeywords() newKeywords = newKeywords()
if hasattr(newKeywords,'capitalize'): # is it string-like ? if hasattr(newKeywords,'capitalize'): # is it string-like ?
...@@ -119,7 +119,8 @@ class KeywordIndex(UnIndex): ...@@ -119,7 +119,8 @@ class KeywordIndex(UnIndex):
manage_addKeywordIndexForm = DTMLFile('dtml/addKeywordIndex', globals()) manage_addKeywordIndexForm = DTMLFile('dtml/addKeywordIndex', globals())
def manage_addKeywordIndex(self, id, REQUEST=None, RESPONSE=None, URL3=None): def manage_addKeywordIndex(self, id, extra=None,
REQUEST=None, RESPONSE=None, URL3=None):
"""Add a keyword index""" """Add a keyword index"""
return self.manage_addIndex(id, 'KeywordIndex', extra=None, \ return self.manage_addIndex(id, 'KeywordIndex', extra=extra, \
REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3) REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3)
...@@ -24,6 +24,19 @@ that have one or more keywords specified in a search query. ...@@ -24,6 +24,19 @@ that have one or more keywords specified in a search query.
<input type="text" name="id" size="40" /> <input type="text" name="id" size="40" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Indexed attributes
</div>
</td>
<td align="left" valign="top">
<input type="text" name="extra.indexed_attrs:record:string" size="40" />
<em>attribute1,attribute2,...</em> or leave empty
</td>
</tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-optional"> <div class="form-optional">
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
############################################################################## ##############################################################################
__version__ = '$Id: PathIndex.py,v 1.30 2002/12/05 21:35:53 caseman Exp $' __version__ = '$Id: PathIndex.py,v 1.31 2003/01/23 17:46:27 andreasjung Exp $'
from Products.PluginIndexes import PluggableIndex from Products.PluginIndexes import PluggableIndex
from Products.PluginIndexes.common.util import parseIndexRequest from Products.PluginIndexes.common.util import parseIndexRequest
...@@ -341,6 +341,11 @@ class PathIndex(Persistent, Implicit, SimpleItem): ...@@ -341,6 +341,11 @@ class PathIndex(Persistent, Implicit, SimpleItem):
return self._index.keys() return self._index.keys()
def getIndexSourceNames(self):
""" return names of indexed attributes """
return ('getPhysicalPath', )
def getEntryForObject(self,documentId,default=_marker): def getEntryForObject(self,documentId,default=_marker):
""" Takes a document ID and returns all the information we have """ Takes a document ID and returns all the information we have
on that specific object. """ on that specific object. """
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
"""Text Index """Text Index
""" """
__version__ = '$Revision: 1.34 $'[11:-2] __version__ = '$Revision: 1.35 $'[11:-2]
import re import re
...@@ -644,6 +644,10 @@ class TextIndex(Persistent, Implicit, SimpleItem): ...@@ -644,6 +644,10 @@ class TextIndex(Persistent, Implicit, SimpleItem):
return query[0] return query[0]
def getIndexSourceNames(self):
""" return name of indexed attributes """
return (self.id, )
def numObjects(self): def numObjects(self):
""" return number of index objects """ """ return number of index objects """
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
############################################################################## ##############################################################################
__version__ = '$Id: TopicIndex.py,v 1.11 2002/12/05 21:35:53 caseman Exp $' __version__ = '$Id: TopicIndex.py,v 1.12 2003/01/23 17:46:31 andreasjung Exp $'
from Products.PluginIndexes import PluggableIndex from Products.PluginIndexes import PluggableIndex
from Products.PluginIndexes.common.util import parseIndexRequest from Products.PluginIndexes.common.util import parseIndexRequest
...@@ -214,6 +214,10 @@ class TopicIndex(Persistent, Implicit, SimpleItem): ...@@ -214,6 +214,10 @@ class TopicIndex(Persistent, Implicit, SimpleItem):
RESPONSE.redirect(URL1+'/manage_workspace?' RESPONSE.redirect(URL1+'/manage_workspace?'
'manage_tabs_message=FilteredSet(s)%20updated') 'manage_tabs_message=FilteredSet(s)%20updated')
def getIndexSourceNames(self):
""" return names of indexed attributes """
return ('n/a',)
def manage_clearFilteredSet(self, filterIds=[], URL1=None, \ def manage_clearFilteredSet(self, filterIds=[], URL1=None, \
REQUEST=None,RESPONSE=None): REQUEST=None,RESPONSE=None):
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
############################################################################## ##############################################################################
"""Pluggable Index Interface""" """Pluggable Index Interface"""
__version__='$Revision: 1.8 $'[11:-2] __version__='$Revision: 1.9 $'[11:-2]
import Interface import Interface
...@@ -24,6 +24,11 @@ class PluggableIndexInterface(Interface.Base): ...@@ -24,6 +24,11 @@ class PluggableIndexInterface(Interface.Base):
def getEntryForObject(documentId, default=None): def getEntryForObject(documentId, default=None):
"""Get all information contained for 'documentId'.""" """Get all information contained for 'documentId'."""
def getIndexSourceNames():
""" return a sequence of attribute names that are indexed
by the index.
"""
def index_object(documentId, obj, threshold=None): def index_object(documentId, obj, threshold=None):
"""Index an object. """Index an object.
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
"""Simple column indices""" """Simple column indices"""
__version__='$Revision: 1.16 $'[11:-2] __version__='$Revision: 1.17 $'[11:-2]
from Globals import Persistent from Globals import Persistent
from Acquisition import Implicit from Acquisition import Implicit
...@@ -38,7 +38,7 @@ class UnIndex(Persistent, Implicit, SimpleItem): ...@@ -38,7 +38,7 @@ class UnIndex(Persistent, Implicit, SimpleItem):
"""UnIndex object interface""" """UnIndex object interface"""
def __init__(self, id, ignore_ex=None, call_methods=None): def __init__(self, id, ignore_ex=None, call_methods=None, extra=None, caller=None):
"""Create an unindex """Create an unindex
UnIndexes are indexes that contain two index components, the UnIndexes are indexes that contain two index components, the
...@@ -69,16 +69,27 @@ class UnIndex(Persistent, Implicit, SimpleItem): ...@@ -69,16 +69,27 @@ class UnIndex(Persistent, Implicit, SimpleItem):
You will also need to pass in an object in the index and You will also need to pass in an object in the index and
uninded methods for this to work. uninded methods for this to work.
'extra' -- a record-style object that keeps additional
index-related parameters
'caller' -- reference to the calling object (usually
a (Z)Catalog instance
""" """
self.id = id self.id = id
self.ignore_ex=ignore_ex # currently unimplimented self.ignore_ex=ignore_ex # currently unimplimented
self.call_methods=call_methods self.call_methods=call_methods
# experimental code for specifing the operator self.operators = ('or', 'and')
self.operators = ['or','and']
self.useOperator = 'or' self.useOperator = 'or'
# allow index to index multiple attributes
try:
self.indexed_attrs = extra.indexed_attrs.split(',')
self.indexed_attrs = [ attr.strip() for attr in self.indexed_attrs if attr ]
except: self.indexed_attrs = [ self.id ]
self.__len__=BTrees.Length.Length() # see __len__ method docstring self.__len__=BTrees.Length.Length() # see __len__ method docstring
self.clear() self.clear()
...@@ -214,13 +225,28 @@ class UnIndex(Persistent, Implicit, SimpleItem): ...@@ -214,13 +225,28 @@ class UnIndex(Persistent, Implicit, SimpleItem):
indexRow=IITreeSet((indexRow, documentId)) indexRow=IITreeSet((indexRow, documentId))
self._index[entry] = indexRow self._index[entry] = indexRow
def index_object(self, documentId, obj, threshold=None): def index_object(self, documentId, obj, threshold=None):
""" wrapper to handle indexing of multiple attributes """
# needed for backward compatibility
try: fields = self.indexed_attrs
except: fields = [ self.id ]
res = 0
for attr in fields:
res += self._index_object(documentId, obj, threshold, attr)
return res > 0
def _index_object(self, documentId, obj, threshold=None, attr=''):
""" index and object 'obj' with integer id 'documentId'""" """ index and object 'obj' with integer id 'documentId'"""
global _marker global _marker
returnStatus = 0 returnStatus = 0
# First we need to see if there's anything interesting to look at # First we need to see if there's anything interesting to look at
datum = self._get_object_datum(obj) datum = self._get_object_datum(obj, attr)
# We don't want to do anything that we don't have to here, so we'll # We don't want to do anything that we don't have to here, so we'll
# check to see if the new and existing information is the same. # check to see if the new and existing information is the same.
...@@ -244,12 +270,12 @@ class UnIndex(Persistent, Implicit, SimpleItem): ...@@ -244,12 +270,12 @@ class UnIndex(Persistent, Implicit, SimpleItem):
return returnStatus return returnStatus
def _get_object_datum(self,obj): def _get_object_datum(self,obj, attr):
# self.id is the name of the index, which is also the name of the # self.id is the name of the index, which is also the name of the
# attribute we're interested in. If the attribute is callable, # attribute we're interested in. If the attribute is callable,
# we'll do so. # we'll do so.
try: try:
datum = getattr(obj, self.id) datum = getattr(obj, attr)
if callable(datum): if callable(datum):
datum = datum() datum = datum()
except AttributeError: except AttributeError:
...@@ -389,6 +415,17 @@ class UnIndex(Persistent, Implicit, SimpleItem): ...@@ -389,6 +415,17 @@ class UnIndex(Persistent, Implicit, SimpleItem):
else: else:
return 0 return 0
def getIndexSourceNames(self):
""" return name of indexed attributes """
return (self.id, )
def getIndexSourceNames(self):
""" return sequence of indexed attributes """
try:
return self.indexed_attrs
except:
return [ self.id ]
def uniqueValues(self, name=None, withLengths=0): def uniqueValues(self, name=None, withLengths=0):
"""\ """\
......
...@@ -131,7 +131,12 @@ function toggleSelect() { ...@@ -131,7 +131,12 @@ function toggleSelect() {
<td align="left" valign="top"> <td align="left" valign="top">
<div class="list-item"> <div class="list-item">
<a href="Indexes/&dtml.url_quote-sequence-key;/manage_workspace"> <a href="Indexes/&dtml.url_quote-sequence-key;/manage_workspace">
&dtml-sequence-key; <dtml-if title>(&dtml-title;)</dtml-if> &dtml-sequence-key;
<dtml-try>
(indexed attrs: <dtml-var "', '.join(_['sequence-item'].getIndexSourceNames())">)
<dtml-except>
<dtml-if title> (&dtml-title;) </dtml-if>
</dtml-try>
</a> </a>
</div> </div>
...@@ -141,7 +146,7 @@ function toggleSelect() { ...@@ -141,7 +146,7 @@ function toggleSelect() {
<td> <td>
<div class="list-item"> <div class="list-item">
<dtml-if "_.string.find(_.str(_.getattr(this(),'__implements__','old')),'PluggableIndexInterface')>-1"> <dtml-if "_.string.find(_.str(_.getattr(this(),'__implements__','old')),'PluggableIndex')>-1">
&dtml-meta_type; &dtml-meta_type;
<dtml-else> <dtml-else>
<dtml-call "REQUEST.set('oldidx',1)"> <dtml-call "REQUEST.set('oldidx',1)">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment