[ckan-changes] commit/ckan: John Glover: [solr] Fix tag searching using Postgres

Bitbucket commits-noreply at bitbucket.org
Mon Aug 22 15:50:48 UTC 2011


1 new changeset in ckan:

http://bitbucket.org/okfn/ckan/changeset/b2c7b5945784/
changeset:   b2c7b5945784
branch:      feature-1275-solr-search
user:        John Glover
date:        2011-08-22 17:50:27
summary:     [solr] Fix tag searching using Postgres
affected #:  3 files (3.4 KB)

--- a/ckan/lib/search/__init__.py	Mon Aug 22 14:51:46 2011 +0100
+++ b/ckan/lib/search/__init__.py	Mon Aug 22 16:50:27 2011 +0100
@@ -5,7 +5,7 @@
 from ckan.lib.dictization.model_dictize import package_to_api1
 from common import SearchError
 from index import PackageSearchIndex, NoopSearchIndex
-from query import PackageSearchQuery, QueryOptions
+from query import TagSearchQuery, PackageSearchQuery, QueryOptions
 
 log = logging.getLogger(__name__)
 
@@ -28,6 +28,7 @@
 }
 
 _QUERIES = {
+    'tag': TagSearchQuery,
     'package': PackageSearchQuery
 }
 


--- a/ckan/lib/search/query.py	Mon Aug 22 14:51:46 2011 +0100
+++ b/ckan/lib/search/query.py	Mon Aug 22 16:50:27 2011 +0100
@@ -182,11 +182,89 @@
         
     def _run(self):
         raise SearchError("SearchQuery._run() not implemented!")
+
+    def _db_query(self, q):
+        # Run the query
+        self.count = q.count()
+        q = q.offset(self.options.get('offset'))
+        q = q.limit(self.options.get('limit'))
+        
+        self.results = []
+        for result in q:
+            if isinstance(result, tuple) and isinstance(result[0], model.DomainObject):
+                # This is the case for order_by rank due to the add_column.
+                self.results.append(result[0])
+            else:
+                self.results.append(result)
         
     # convenience, allows to query(..)
     __call__ = run
 
 
+# TODO: is this code used anywhere? If so, fix it write some tests for it.
+# class GroupSqlSearchQuery(SearchQuery):
+#     """ Search for groups in plain SQL. """
+#     def _run(self):
+#         if not self.query.terms:
+#             return
+#         q = authz.Authorizer().authorized_query(username, model.Group)
+#         for term in self.query.terms:
+#             q = query.filter(model.Group.name.contains(term.lower()))
+#         self._db_query(q)
+
+
+class TagSearchQuery(SearchQuery):
+    """Search for tags in plain SQL."""
+    def _run(self):
+        q = model.Session.query(model.Tag)
+        q = q.distinct().join(model.Tag.package_tags)
+        terms = list(self.query.terms)
+        for field, value in self.query.fields.items():
+            if field in ('tag', 'tags'):
+                terms.append(value)
+        if not len(terms):
+            return
+        for term in terms:
+            q = q.filter(model.Tag.name.contains(term.lower()))
+        self._db_query(q)
+
+
+# class ResourceSqlSearchQuery(SqlSearchQuery):
+#     """ Search for resources in plain SQL. """
+
+#     def _run(self):
+#         q = model.Session.query(model.Resource) # TODO authz
+#         if self.query.terms:
+#             raise SearchError('Only field specific terms allowed in resource search.')
+#         #self._check_options_specified_are_allowed('resource search', ['all_fields', 'offset', 'limit'])
+#         self.options.ref_entity_with_attr = 'id' # has no name
+#         resource_fields = model.Resource.get_columns()
+#         for field, terms in self.query.fields.items():
+#             if isinstance(terms, basestring):
+#                 terms = terms.split()
+#             if field not in resource_fields:
+#                 raise SearchError('Field "%s" not recognised in Resource search.' % field)
+#             for term in terms:
+#                 model_attr = getattr(model.Resource, field)
+#                 if field == 'hash':                
+#                     q = q.filter(model_attr.ilike(unicode(term) + '%'))
+#                 elif field in model.Resource.get_extra_columns():
+#                     model_attr = getattr(model.Resource, 'extras')
+
+#                     like = or_(model_attr.ilike(u'''%%"%s": "%%%s%%",%%''' % (field, term)),
+#                                model_attr.ilike(u'''%%"%s": "%%%s%%"}''' % (field, term))
+#                               )
+#                     q = q.filter(like)
+#                 else:
+#                     q = q.filter(model_attr.ilike('%' + unicode(term) + '%'))
+        
+#         order_by = self.options.order_by
+#         if order_by is not None:
+#             if hasattr(model.Resource, order_by):
+#                 q = q.order_by(getattr(model.Resource, order_by))
+#         self._db_query(q)
+
+
 class PackageSearchQuery(SearchQuery):
     def _run(self):
         fq = ""


--- a/ckan/tests/functional/api/test_action.py	Mon Aug 22 14:51:46 2011 +0100
+++ b/ckan/tests/functional/api/test_action.py	Mon Aug 22 16:50:27 2011 +0100
@@ -2,6 +2,8 @@
 from pprint import pprint, pformat
 from nose.tools import assert_equal
 
+from ckan import plugins
+import ckan.lib.search as search
 from ckan.lib.create_test_data import CreateTestData
 import ckan.model as model
 from ckan.tests import WsgiAppCase
@@ -22,15 +24,16 @@
 
     @classmethod
     def setup_class(self):
+        search.clear()
+        plugins.load('synchronous_search')
         CreateTestData.create()
-
         self.sysadmin_user = model.User.get('testsysadmin')
-
         self.normal_user = model.User.get('annafan')
 
     @classmethod
     def teardown_class(self):
         model.repo.rebuild_db()
+        search.clear()
 
     def test_01_package_list(self):
         postparams = '%s=1' % json.dumps({})
@@ -461,6 +464,7 @@
         postparams = '%s=1' % json.dumps({'q':'r'})
         res = self.app.post('/api/action/tag_autocomplete', params=postparams)
         res_obj = json.loads(res.body)
+        print res_obj
         assert res_obj == {
             'help': 'Returns tags containing the provided string', 
             'result': ['russian'],

Repository URL: https://bitbucket.org/okfn/ckan/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.




More information about the ckan-changes mailing list