diff --git a/src/python/xesam/xesam-recoll-service b/src/python/xesam/xesam-recoll-service index a9aafdcf..2da32365 100755 --- a/src/python/xesam/xesam-recoll-service +++ b/src/python/xesam/xesam-recoll-service @@ -73,6 +73,8 @@ class RecollSearch (xesam.server.Search): def __init__ (self, searcher, session, search_handle, \ query=None, xml=None) : + # Our parent class does possible xml-to-query parsing. We end up + # with a query xesam.server.Search.__init__ (self, searcher, session, search_handle, \ query=query, xml=xml) @@ -85,11 +87,9 @@ class RecollSearch (xesam.server.Search): xesam.debug ("Created %s with handle %s and query:\n%s" % (self.__class__, self.get_handle(), self.get_query())) - # Only user queries for now... - if not isinstance(self.get_query(), xesam.query.UserQuery): - raise Exception ("Only UserQuery supported ATM, sorry.") + # Instantiate a recoll query self.rclquery = self._searcher.rcldb.query() - + # In the latest version (>0.95), primary/secondary is replaced by # a field list. sortfield = session.get_property(xesam.SESSION_SORT_PRIMARY) @@ -105,26 +105,37 @@ class RecollSearch (xesam.server.Search): if sortfield: self.rclquery.sortby(sortfield, order == "ascending" and 1 or 0) + def doc_to_hit(self, doc): + data = [] + for fld in self._hit_fields: + # Need to handle ContentCategory and SourceCategory + fld = fld.lower().replace("xesam:", "") + xesam.debug("Adding data for fld %s" % (fld)) + if fld == "snippet": + data.append(self._searcher.rcldb.makeDocAbstract(doc, + self.rclquery)) + elif fld == "contentmodified": + data.append(timestampToIso8601(getattr(doc, "mtime"))) + else: + data.append(getattr(doc, fld, "")) + return data + def start (self): - xesam.debug ("RecollSearch '%s' got [%s]" % - (self.get_handle(), self.get_query().get_string())) - self.nres = self.rclquery.execute(self.get_query().get_string()) + xesam.debug ("RecollSearch") + + if isinstance(self.get_query(), xesam.query.UserQuery): + self.nres = self.rclquery.execute(self.get_query().get_string()) + elif isinstance(self.get_query(), xesam.query.CompositeQuery): + self.build_search(None) + self.nres = self.rclquery.executesd(self.searchdata) + else: + raise Exception ("Neither UserQuery nor composite query ??") + hits = 0 done = 0 while self.rclquery.next >= 0 and self.rclquery.next < self.nres: doc = self.rclquery.fetchone() - data = [] - for fld in self._hit_fields: - # Need to handle ContentCategory and SourceCategory - fld = fld.lower().replace("xesam:", "") - xesam.debug("Adding data for fld %s" % (fld)) - if fld == "snippet": - data.append(self._searcher.rcldb.makeDocAbstract(doc, - self.rclquery)) - elif fld == "contentmodified": - data.append(timestampToIso8601(getattr(doc, "mtime"))) - else: - data.append(getattr(doc, fld, "")) + data = self.doc_to_hit(doc) self.add_new_hit (self._hit_fields, data) hits += 1 if hits >= self.SLICE: @@ -149,15 +160,10 @@ class RecollSearch (xesam.server.Search): return xesam.server.Search.get_hits(self, num_hits) hits = 0 - done = 0; + done = 0 while self.rclquery.next >= 0 and self.rclquery.next < self.nres: doc = self.rclquery.fetchone() - data = [] - for fld in self._hit_fields: - if self.FLDTRANS.has_key (fld): - data.append(self.FLDTRANS[fld](doc)) - else: - data.append("") + data = self.doc_to_hit(doc) self.add_new_hit (self._hit_fields, data) hits += 1 if hits >= self.SLICE or hits >= num_hits: @@ -176,6 +182,50 @@ class RecollSearch (xesam.server.Search): return xesam.server.Search.get_hits(self, num_hits) + # Build Recoll searchData tree out of Xesam CompositeQuery + # This is recursive, parent is the current SearchData into which we are + # adding clauses/subsearches. + def build_search(self, parent = None): + +Arrete apres le hackfest parce qu'apparemment il y a de gros changements la +dedans. + +Il manque plein de trucs, comme traiter les "names" des selectors (see +xesam/query.py: SELECTORS, traiter les differents types de values, et leurs +attributs (phrase, slack, ordered etc, cf xesam/query.py: StringValue + + + xq = self.get_query() + cl = xq.get_clause() + if isinstance(cl, xesam.query.SelectorClause): + xesam.debug ("Selector clause") + if parent is None: + # Top clause is a selector. Needs to have a parent + self.searchdata = recoll.SearchData() + parent = self.searchdata + + # Fields. If there are several we must turn this into an OR + # combination of searches on the different fields + nfields = length(cl.get_fields()) + if nfields > 1: + orsearch = recoll.SearchData(type = "or") + for fld in cl.get_fields(): + simple_selec_addclause(self, orsearch, cl, fld) + parent.addclause(type = "sub", subSearch = orsearch) + elif nfields == 1: + simple_selec_addclause(self, parent, cl, cl.get_fields[0]) + else: + simple_selec_addclause(self, parent, cl) + elif isinstance(cl, xesam.query.CollectorClause): + xesam.debug ("Collector clause") + else: + raise Exception("Non Collector or Selector Clause found") + + # Add Recoll clause for xesam selector clause, dealing with at most + # one field. + def simple_selec_addclause(self, parent, cl, fld = ""): + parent.addclause(type = "and", field = fld, + qstring = cl.get_value().get()) if __name__ == "__main__": RecollServer().start()