Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Saller <bcsaller@objectrealms.net>2007-07-04 21:04:36 (GMT)
committer Benjamin Saller <bcsaller@objectrealms.net>2007-07-04 21:04:36 (GMT)
commit18b79510269fa0c6bb5380e6634aebc943d6d556 (patch)
treefa8396358f64f6843c3eb983a439d9c9b59f281c
parent89447c06440d60ea741771a0c63e75cc337c11ca (diff)
parentc39ce046917e98096ab199aa231bd5614e3896c3 (diff)
pull branch
Merge branch 'listprops'
-rwxr-xr-xbin/index-service17
-rwxr-xr-xbin/sample-client.py2
-rw-r--r--src/olpc/datastore/datastore.py35
-rw-r--r--src/olpc/datastore/indexer.py1
-rw-r--r--src/olpc/datastore/query.py53
-rw-r--r--tests/query.txt11
6 files changed, 84 insertions, 35 deletions
diff --git a/bin/index-service b/bin/index-service
index 6a7fc2d..4529913 100755
--- a/bin/index-service
+++ b/bin/index-service
@@ -75,6 +75,15 @@ class IndexService(Application):
self.eventloop.run()
+ def get_textprops(self, uid):
+ # text properties also get full text indexing
+ # currently this is still searched with the 'fulltext'
+ # parameter of find()
+ textprops = {}
+ for p in self.ds.get_properties(uid, type='text'):
+ textprops[p.key] = p.value and p.value or ''
+ return textprops
+
def created(self, uid):
"""An object was created on the bus and we want to index it"""
# because the file isn't encoded anywhere accessible in the
@@ -84,7 +93,8 @@ class IndexService(Application):
r = None
if filename:
mime_type = self.ds.get_properties(uid).get('mime_type', None)
- r = self.fulltext.fulltext_index(uid, filename, mime_type)
+ r = self.fulltext.fulltext_index(uid, filename, mime_type,
+ **self.get_textprops(uid))
if r is True:
logger.debug("index creation of %s" % uid)
elif r is False:
@@ -102,7 +112,8 @@ class IndexService(Application):
if filename:
mime_type = self.ds.get_properties(uid).get('mime_type', None)
print uid, filename, mime_type
- r = self.fulltext.fulltext_index(uid, filename, mime_type)
+ r = self.fulltext.fulltext_index(uid, filename, mime_type,
+ **self.get_textprops(uid))
if r is True:
logger.debug("index update of %s" % uid)
elif r is False:
@@ -139,7 +150,7 @@ if __name__ == "__main__":
signal.signal(signal.SIGTERM, handle_shutdown)
idx = IndexService()
- ##idx()
+ #idx()
# w/o ore.main
import gobject
diff --git a/bin/sample-client.py b/bin/sample-client.py
index 1a2475d..bd609a7 100755
--- a/bin/sample-client.py
+++ b/bin/sample-client.py
@@ -35,6 +35,8 @@ def main():
print datastore.find(dict(fulltext="amazed"))
datastore.get_properties(uid)
+ print "title in fulltext", datastore.find(dict(fulltext="another"))
+
datastore.delete(uid)
if __name__ == '__main__':
diff --git a/src/olpc/datastore/datastore.py b/src/olpc/datastore/datastore.py
index b4fe356..142d801 100644
--- a/src/olpc/datastore/datastore.py
+++ b/src/olpc/datastore/datastore.py
@@ -109,6 +109,24 @@ class DataStore(dbus.service.Object):
self.mountpoints[mountpoint_id].stop()
del self.mountpoints[mountpoint_id]
### End Mount Points
+
+ ### Buddy Management
+ ## A single datastore typically refers to a single user
+ ## this breaks down a little in the case of things like USB
+ ## sticks and so on. We provide a facility for tracking
+ ## co-authors of content
+ ## there are associated changes to 'find' to resolve buddies
+ def addBuddy(self, id, name, fg_color, bg_color):
+ pass
+
+ def getBuddy(self, id):
+ pass
+
+ def buddies(self):
+ pass
+
+
+ ## end buddy api
def connect_backingstore(self, uri, **kwargs):
"""
@@ -227,6 +245,13 @@ class DataStore(dbus.service.Object):
don't want to generate them unless needed. In the case the
the full properties set matches doing the single roundtrip
to start an activity makes sense.
+
+ To order results by a given property you can specify:
+ >>> ds.find(order_by=['author', 'title'])
+
+ Order by must be a list of property names given in the order
+ of decreasing precedence.
+
"""
# only goes to the primary now. Punting on the merge case
if isinstance(query, dict):
@@ -234,7 +259,7 @@ class DataStore(dbus.service.Object):
include_files = kwargs.pop('include_files', False)
order_by = kwargs.pop('order_by', [])
-
+
# distribute the search to all the mountpoints unless a
# backingstore id set is specified
results, count = self._multiway_search(kwargs)
@@ -272,7 +297,6 @@ class DataStore(dbus.service.Object):
return 0
-
r = results.values()
r.sort(comparator)
results = r
@@ -330,12 +354,13 @@ class DataStore(dbus.service.Object):
#@utils.sanitize_dbus
@dbus.service.method(DS_DBUS_INTERFACE,
- in_signature='s',
+ in_signature='sa{sv}',
out_signature='a{sv}')
- def get_properties(self, uid):
+ def get_properties(self, uid, query=None):
content = self.get(uid)
dictionary = {}
- for prop in content.get_properties():
+ if not query: query = {}
+ for prop in content.get_properties(**query):
dictionary[prop.key] = prop.marshall()
return dictionary
diff --git a/src/olpc/datastore/indexer.py b/src/olpc/datastore/indexer.py
index 8d132ad..de7ef33 100644
--- a/src/olpc/datastore/indexer.py
+++ b/src/olpc/datastore/indexer.py
@@ -44,3 +44,4 @@ class Indexer(dbus.service.Object, XapianFulltext):
self.connect_fulltext(repo, read_only=False)
+
diff --git a/src/olpc/datastore/query.py b/src/olpc/datastore/query.py
index 93a50b5..2c5dd9f 100644
--- a/src/olpc/datastore/query.py
+++ b/src/olpc/datastore/query.py
@@ -200,7 +200,8 @@ class QueryManager(SugarDomain):
if self.sync_index and filelike:
self.fulltext_index(c.id, filelike,
- mimetype=c.get_property('mime_type'))
+ mimetype=c.get_property('mime_type'),
+ textprops=self.get_textprops(c))
return c
@@ -212,7 +213,7 @@ class QueryManager(SugarDomain):
self.model.session.flush()
if self.sync_index and filelike:
- self.fulltext_index(content.id, filelike)
+ self.fulltext_index(content.id, filelike, textprops=self.get_textprops(content))
def _bindProperties(self, content, props, creating=False, include_defaults=False):
@@ -285,11 +286,6 @@ class QueryManager(SugarDomain):
of content matching its parameters. see fulltext_search for
additional details.
- To order results by a given property you can specify:
- >>> qm.find(order_by=['author', 'title'])
-
- Order by must be a list of property names given in the order
- of decreasing precedence.
If 'limit' is passed it will be the maximum number of results
to return and 'offset' will be the offset from 0 into the
@@ -339,9 +335,14 @@ class QueryManager(SugarDomain):
if ctime or mtime:
self._query_dates(ctime, mtime, where)
for k,v in query.iteritems():
+ if isinstance(v, list):
+ v = properties.c.value.in_(*v)
+ else:
+ v = properties.c.value==v
+
where.append(select([properties.c.content_id],
and_( properties.c.key==k,
- properties.c.value==v)))
+ v)))
statement = intersect(*where)
statement.distinct=True
@@ -422,12 +423,20 @@ class QueryManager(SugarDomain):
return s
-
+ def get_textprops(self, uid_or_content):
+ # text properties also get full text indexing
+ # currently this is still searched with the 'fulltext'
+ # parameter of find()
+ content = self._resolve(uid_or_content)
+ textprops = {}
+ for p in content.get_properties(type='text'):
+ textprops[p.key] = p.value and p.value or ''
+ return textprops
# fulltext interface
- def fulltext_index(self, uid, fileobj, mimetype=None):
+ def fulltext_index(self, uid, fileobj, mimetype=None, textprops=None):
"""Index the fileobj relative to uid which should be a
olpc.datastore.model.Content object's uid. The fileobj can be
either a pathname or an object implementing the Python file
@@ -533,7 +542,7 @@ class XapianFulltext(object):
self.index.registerFlattener(unicode, flatten_unicode)
atexit.register(self.index.close)
- def fulltext_index(self, uid, fileobj, mimetype=None):
+ def fulltext_index(self, uid, fileobj, mimetype=None, textprops=None):
"""Index the fileobj relative to uid which should be a
olpc.datastore.model.Content's uid. The fileobj can be either
a pathname or an object implementing the Python file ('read')
@@ -558,27 +567,17 @@ class XapianFulltext(object):
# into an indexable form.
logging.debug("Unable to index %s %s" % (uid, fileobj))
return False
-
- # text properties also get full text indexing
- # currently this is still searched with the 'fulltext'
- # parameter of find()
- textprops = {}
- """
- content = self.get(uid)
- for p in content.get_properties(type='text'):
- textprops[p.key] = p.value and p.value or ''
- """
-
return self._ft_index(uid, fp, piece, textprops)
def _ft_index(self, content_id, fp, piece=DocumentPiece, fields=None):
try:
doc = [piece(fp.read())]
- # add in properties that need extra fulltext like
- # management
- for key, value in fields.iteritems():
- doc.append(DocumentPiece(value, key))
-
+ if fields:
+ # add in properties that need extra fulltext like
+ # management
+ for key, value in fields.iteritems():
+ doc.append(DocumentPiece(value, key))
+
self.index.addDocument(doc, content_id)
self.index.flush()
return True
diff --git a/tests/query.txt b/tests/query.txt
index 9a16eca..e1f3791 100644
--- a/tests/query.txt
+++ b/tests/query.txt
@@ -255,6 +255,17 @@ used in the 'author' field.
>>> assert set(qm.get_uniquevaluesfor('author')) == set(['Benjamin', 'Sarah'])
+Now that we can see a set of possible values it might be nice to
+select any content with properties from a known set. For example
+
+>>> r, c = qm.find(author=['Benjamin', 'Sarah'])
+>>> assert c == 3
+
+By putting the request value in a list we can ask that the value be
+'IN' this collection. All participating values are included in this
+way.
+
+
Now for politeness we shut everything down
>>> qm.stop()
>>> import shutil, os