[ckan-changes] commit/ckan: John Glover: [search] Move resource search function to logic layer
Bitbucket
commits-noreply at bitbucket.org
Tue Sep 20 14:49:57 UTC 2011
1 new changeset in ckan:
http://bitbucket.org/okfn/ckan/changeset/1cecc34f9055/
changeset: 1cecc34f9055
branch: feature-1302-resource-tag-search
user: John Glover
date: 2011-09-20 16:49:18
summary: [search] Move resource search function to logic layer
affected #: 3 files (-1 bytes)
--- a/ckan/lib/search/query.py Tue Sep 20 12:07:57 2011 +0100
+++ b/ckan/lib/search/query.py Tue Sep 20 15:49:18 2011 +0100
@@ -4,6 +4,7 @@
from paste.util.multidict import MultiDict
from paste.deploy.converters import asbool
from ckan import model
+from ckan.logic import get_action
from common import make_connection, SearchError
import logging
log = logging.getLogger(__name__)
@@ -219,7 +220,7 @@
class TagSearchQuery(SearchQuery):
- """Search for tags in plain SQL."""
+ """Search for tags."""
def _run(self):
q = model.Session.query(model.Tag)
q = q.distinct().join(model.Tag.package_tags)
@@ -235,38 +236,29 @@
class ResourceSearchQuery(SearchQuery):
- """ 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.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')
+ """Search for resources."""
+ def run(self, query=None, terms=[], fields={}, facet_by=[], options=None, **kwargs):
+ if options is None:
+ options = QueryOptions(**kwargs)
+ else:
+ options.update(kwargs)
- 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)
+ context = {'model':model, 'session': model.Session}
+ data_dict = {
+ 'fields': fields,
+ 'offset': options.get('offset'),
+ 'limit': options.get('limit'),
+ 'order_by': options.get('order_by')
+ }
+ results = get_action('resource_search')(context, data_dict)
+
+ # if options.all_fields is set, return a dict
+ # if not, return a list of resource IDs
+ if options.all_fields:
+ results['results'] = [r.as_dict() for r in results['results']]
+ else:
+ results['results'] = [r.id for r in results['results']]
+ return results
class PackageSearchQuery(SearchQuery):
--- a/ckan/logic/action/get.py Tue Sep 20 12:07:57 2011 +0100
+++ b/ckan/logic/action/get.py Tue Sep 20 15:49:18 2011 +0100
@@ -21,7 +21,7 @@
group_to_api2,
tag_to_api1,
tag_to_api2)
-from ckan.lib.search import query_for
+from ckan.lib.search import query_for, SearchError
def site_read(context,data_dict=None):
check_access('site_read',context,data_dict)
@@ -625,3 +625,54 @@
package_dict['isopen'] = False
return package_dict
+
+def resource_search(context, data_dict):
+ model = context['model']
+ session = context['session']
+
+ fields = data_dict['fields']
+ order_by = data_dict.get('order_by')
+ offset = data_dict.get('offset')
+ limit = data_dict.get('limit')
+
+ # TODO: should we check for user authentication first?
+ q = model.Session.query(model.Resource)
+ resource_fields = model.Resource.get_columns()
+
+ for field, terms in 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) + '%'))
+
+ if order_by is not None:
+ if hasattr(model.Resource, order_by):
+ q = q.order_by(getattr(model.Resource, order_by))
+
+ count = q.count()
+ q = q.offset(offset)
+ q = q.limit(limit)
+
+ 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.
+ results.append(result[0])
+ else:
+ results.append(result)
+
+ return {'count': count, 'results': results}
--- a/ckan/tests/lib/test_resource_search.py Tue Sep 20 12:07:57 2011 +0100
+++ b/ckan/tests/lib/test_resource_search.py Tue Sep 20 15:49:18 2011 +0100
@@ -148,7 +148,7 @@
resources = result['results']
count = result['count']
assert len(resources) == 2, resources
- assert count == all_resource_count
+ assert count == all_resource_count, (count, all_resource_count)
assert resources == all_resources[:2], '%r, %r' % (resources, all_resources)
# offset
@@ -182,5 +182,3 @@
# can't be searched
fields = {'size_extra':'100'}
assert_raises(search.SearchError, search.query_for(model.Resource).run, fields=fields)
-
-
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