diff options
author | Benjamin Saller <bcsaller@objectrealms.net> | 2007-07-04 21:04:36 (GMT) |
---|---|---|
committer | Benjamin Saller <bcsaller@objectrealms.net> | 2007-07-04 21:04:36 (GMT) |
commit | 18b79510269fa0c6bb5380e6634aebc943d6d556 (patch) | |
tree | fa8396358f64f6843c3eb983a439d9c9b59f281c | |
parent | 89447c06440d60ea741771a0c63e75cc337c11ca (diff) | |
parent | c39ce046917e98096ab199aa231bd5614e3896c3 (diff) |
pull branch
Merge branch 'listprops'
-rwxr-xr-x | bin/index-service | 17 | ||||
-rwxr-xr-x | bin/sample-client.py | 2 | ||||
-rw-r--r-- | src/olpc/datastore/datastore.py | 35 | ||||
-rw-r--r-- | src/olpc/datastore/indexer.py | 1 | ||||
-rw-r--r-- | src/olpc/datastore/query.py | 53 | ||||
-rw-r--r-- | tests/query.txt | 11 |
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 |