hurry.query

HomePage: http://pypi.python.org/pypi/hurry.query

Author: Infrae

Download: https://pypi.python.org/packages/source/h/hurry.query/hurry.query-1.1.1.tar.gz

        Hurry Query
===========

The hurry query system for the zope.catalog builds on its catalog
indexes, as well as the indexes in zc.catalog. It is in part inspired
by AdvancedQuery for Zope 2 by Dieter Maurer, though has an independent
origin.

.. contents::

Setup
-----

Let's define a simple content object. First its interface::

  >>> from zope.interface import Interface, Attribute, implements
  >>> class IContent(Interface):
  ...     f1 = Attribute('f1')
  ...     f2 = Attribute('f2')
  ...     f3 = Attribute('f3')
  ...     f4 = Attribute('f4')
  ...     t1 = Attribute('t1')
  ...     t2 = Attribute('t2')

And its implementation::

  >>> from zope.container.contained import Contained
  >>> class Content(Contained):
  ...     implements(IContent)
  ...     def __init__(self, id, f1='', f2='', f3='', f4='', t1='', t2=''):
  ...         self.id = id
  ...         self.f1 = f1
  ...         self.f2 = f2
  ...         self.f3 = f3
  ...         self.f4 = f4
  ...         self.t1 = t1
  ...         self.t2 = t2
  ...     def __cmp__(self, other):
  ...         return cmp(self.id, other.id)

The id attribute is just so we can identify objects we find again
easily. By including the __cmp__ method we make sure search results
can be stably sorted.

We use a fake int id utility here so we can test independent of
the full-blown zope environment::

  >>> from zope import interface
  >>> import zope.intid.interfaces
  >>> class DummyIntId(object):
  ...     interface.implements(zope.intid.interfaces.IIntIds)
  ...     MARKER = '__dummy_int_id__'
  ...     def __init__(self):
  ...         self.counter = 0
  ...         self.data = {}
  ...     def register(self, obj):
  ...         intid = getattr(obj, self.MARKER, None)
  ...         if intid is None:
  ...             setattr(obj, self.MARKER, self.counter)
  ...             self.data[self.counter] = obj
  ...             intid = self.counter
  ...             self.counter += 1
  ...         return intid
  ...     def getObject(self, intid):
  ...         return self.data[intid]
  ...     def __iter__(self):
  ...         return iter(self.data)
  >>> intid = DummyIntId()
  >>> from zope.component import provideUtility
  >>> provideUtility(intid, zope.intid.interfaces.IIntIds)

Now let's register a catalog::

  >>> from zope.catalog.interfaces import ICatalog
  >>> from zope.catalog.catalog import Catalog
  >>> catalog = Catalog()
  >>> provideUtility(catalog, ICatalog, 'catalog1')

And set it up with various indexes::

  >>> from zope.catalog.field import FieldIndex
  >>> from zope.catalog.text import TextIndex
  >>> catalog['f1'] = FieldIndex('f1', IContent)
  >>> catalog['f2'] = FieldIndex('f2', IContent)
  >>> catalog['f3'] = FieldIndex('f3', IContent)
  >>> catalog['f4'] = FieldIndex('f4', IContent)
  >>> catalog['t1'] = TextIndex('t1', IContent)
  >>> catalog['t2'] = TextIndex('t2', IContent)

Now let's create some objects so that they'll be cataloged::

  >>> content = [
  ... Content(1, 'a', 'b', 'd'),
  ... Content(2, 'a', 'c'),
  ... Content(3, 'X', 'c'),
  ... Content(4, 'a', 'b', 'e'),
  ... Content(5, 'X', 'b', 'e'),
  ... Content(6, 'Y', 'Z')]

And catalog them now::

  >>> for entry in content:
  ...     catalog.index_doc(intid.register(entry), entry)

Now let's register a query utility::

  >>> from hurry.query.query import Query
  >>> from hurry.query.interfaces import IQuery
  >>> provideUtility(Query(), IQuery)

Set up some code to make querying and display the result
easy::

  >>> from zope.component import getUtility
  >>> from hurry.query.interfaces import IQuery
  >>> def displayQuery(q, context=None):
  ...     query = getUtility(IQuery)
  ...     r = query.searchResults(q, context)
  ...     return [e.id for e in sorted(list(r))]

FieldIndex Queries
------------------

Now for a query where f1 equals a::

  >>> from hurry.query import Eq
  >>> f1 = ('catalog1', 'f1')
  >>> displayQuery(Eq(f1, 'a'))
  [1, 2, 4]

Not equals (this is more efficient than the generic ~ operator)::

  >>> from hurry.query import NotEq
  >>> displayQuery(NotEq(f1, 'a'))
  [3, 5,