Skip to content

Commit

Permalink
[#1838] Calculate FTS rankings only on specific columns
Browse files Browse the repository at this point in the history
The bug was that when we've done a full-text query on a specific column, the
query was OK, but the rank was calculated using all text from the row. It
messed up when trying to get DISTINCT values.
  • Loading branch information
vitorbaptista committed Jul 21, 2014
1 parent 27f5422 commit ed9ece0
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
9 changes: 7 additions & 2 deletions ckanext/datastore/plugin.py
Expand Up @@ -484,9 +484,14 @@ def _build_query_and_rank_statements(self, lang, query, plain, field=None):
statement = u"plainto_tsquery('{lang}', '{query}') {alias}"
else:
statement = u"to_tsquery('{lang}', '{query}') {alias}"
rank_statement = u'ts_rank(_full_text, {query_alias}, 32) AS {alias}'
if field is None:
rank_field = '_full_text'
else:
rank_field = 'to_tsvector("%s")' % field
rank_statement = u'ts_rank({rank_field}, {query_alias}, 32) AS {alias}'
statement = statement.format(lang=lang, query=query, alias=query_alias)
rank_statement = rank_statement.format(query_alias=query_alias,
rank_statement = rank_statement.format(rank_field=rank_field,
query_alias=query_alias,
alias=rank_alias)
return statement, rank_statement

Expand Down
35 changes: 35 additions & 0 deletions ckanext/datastore/tests/test_search.py
Expand Up @@ -14,11 +14,46 @@
from ckanext.datastore.tests.helpers import extract, rebuild_all_dbs

import ckan.new_tests.helpers as helpers
import ckan.new_tests.factories as factories

assert_equals = nose.tools.assert_equals
assert_raises = nose.tools.assert_raises


class TestDatastoreSearchNewTest(object):
@classmethod
def setup_class(cls):
p.load('datastore')

@classmethod
def teardown_class(cls):
p.unload('datastore')
helpers.reset_db()

def test_fts_on_field_calculates_ranks_only_on_that_specific_field(self):
resource = factories.Resource()
data = {
'resource_id': resource['id'],
'force': True,
'records': [
{'from': 'Brazil', 'to': 'Brazil'},
{'from': 'Brazil', 'to': 'Italy'}
],
}
result = helpers.call_action('datastore_create', **data)
search_data = {
'resource_id': resource['id'],
'fields': 'from',
'q': {
'from': 'Brazil'
},
}
result = helpers.call_action('datastore_search', **search_data)
ranks = [r['rank from'] for r in result['records']]
assert_equals(len(result['records']), 2)
assert_equals(len(set(ranks)), 1)


class TestDatastoreSearch(tests.WsgiAppCase):
sysadmin_user = None
normal_user = None
Expand Down

0 comments on commit ed9ece0

Please sign in to comment.