зеркало из https://github.com/mozilla/kitsune.git
[bug 1007319] Switch to match and match_phrase queries.
This commit is contained in:
Родитель
e9ae83042a
Коммит
a7283e188f
|
@ -272,21 +272,21 @@ These are the default weights that apply to all searches:
|
||||||
|
|
||||||
wiki (aka kb)::
|
wiki (aka kb)::
|
||||||
|
|
||||||
document_title__text 6
|
document_title__match 6
|
||||||
document_content__text 1
|
document_content__match 1
|
||||||
document_keywords__text 8
|
document_keywords__match 8
|
||||||
document_summary__text 2
|
document_summary__match 2
|
||||||
|
|
||||||
questions (aka support forums)::
|
questions (aka support forums)::
|
||||||
|
|
||||||
question_title__text 4
|
question_title__match 4
|
||||||
question_content__text 3
|
question_content__match 3
|
||||||
question_answer_content__text 3
|
question_answer_content__match 3
|
||||||
|
|
||||||
forums (aka contributor forums)::
|
forums (aka contributor forums)::
|
||||||
|
|
||||||
post_title__text 2
|
post_title__match 2
|
||||||
post_content__text 1
|
post_content__match 1
|
||||||
|
|
||||||
|
|
||||||
Elastic Search is built on top of Lucene so the `Lucene documentation
|
Elastic Search is built on top of Lucene so the `Lucene documentation
|
||||||
|
|
|
@ -15,7 +15,7 @@ class QuestionUpdateTests(ElasticTestCase):
|
||||||
# Create a question--that adds one document to the index.
|
# Create a question--that adds one document to the index.
|
||||||
q = question(title=u'Does this test work?', save=True)
|
q = question(title=u'Does this test work?', save=True)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
query = dict(('%s__text' % field, 'test')
|
query = dict(('%s__match' % field, 'test')
|
||||||
for field in QuestionMappingType.get_query_fields())
|
for field in QuestionMappingType.get_query_fields())
|
||||||
eq_(search.query(should=True, **query).count(), 1)
|
eq_(search.query(should=True, **query).count(), 1)
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ class QuestionUpdateTests(ElasticTestCase):
|
||||||
a = answer(content=u'There\'s only one way to find out!',
|
a = answer(content=u'There\'s only one way to find out!',
|
||||||
question=q)
|
question=q)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
query = dict(('%s__text' % field, 'only')
|
query = dict(('%s__match' % field, 'only')
|
||||||
for field in QuestionMappingType.get_query_fields())
|
for field in QuestionMappingType.get_query_fields())
|
||||||
eq_(search.query(should=True, **query).count(), 0)
|
eq_(search.query(should=True, **query).count(), 0)
|
||||||
|
|
||||||
a.save()
|
a.save()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
query = dict(('%s__text' % field, 'only')
|
query = dict(('%s__match' % field, 'only')
|
||||||
for field in QuestionMappingType.get_query_fields())
|
for field in QuestionMappingType.get_query_fields())
|
||||||
eq_(search.query(should=True, **query).count(), 1)
|
eq_(search.query(should=True, **query).count(), 1)
|
||||||
|
|
||||||
|
@ -44,11 +44,11 @@ class QuestionUpdateTests(ElasticTestCase):
|
||||||
|
|
||||||
q = question(title=u'Does this work?', save=True)
|
q = question(title=u'Does this work?', save=True)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(search.query(question_title__text='work').count(), 1)
|
eq_(search.query(question_title__match='work').count(), 1)
|
||||||
|
|
||||||
q.delete()
|
q.delete()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(search.query(question_title__text='work').count(), 0)
|
eq_(search.query(question_title__match='work').count(), 0)
|
||||||
|
|
||||||
def test_question_one_answer_deleted(self):
|
def test_question_one_answer_deleted(self):
|
||||||
search = QuestionMappingType.search()
|
search = QuestionMappingType.search()
|
||||||
|
@ -59,19 +59,19 @@ class QuestionUpdateTests(ElasticTestCase):
|
||||||
|
|
||||||
# Question and its answers are a single document--so the
|
# Question and its answers are a single document--so the
|
||||||
# index count should be only 1.
|
# index count should be only 1.
|
||||||
eq_(search.query(question_title__text='pink').count(), 1)
|
eq_(search.query(question_title__match='pink').count(), 1)
|
||||||
|
|
||||||
# After deleting the answer, the question document should
|
# After deleting the answer, the question document should
|
||||||
# remain.
|
# remain.
|
||||||
a.delete()
|
a.delete()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(search.query(question_title__text='pink').count(), 1)
|
eq_(search.query(question_title__match='pink').count(), 1)
|
||||||
|
|
||||||
# Delete the question and it should be removed from the
|
# Delete the question and it should be removed from the
|
||||||
# index.
|
# index.
|
||||||
q.delete()
|
q.delete()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(search.query(question_title__text='pink').count(), 0)
|
eq_(search.query(question_title__match='pink').count(), 0)
|
||||||
|
|
||||||
def test_question_questionvote(self):
|
def test_question_questionvote(self):
|
||||||
search = QuestionMappingType.search()
|
search = QuestionMappingType.search()
|
||||||
|
@ -154,11 +154,11 @@ class QuestionUpdateTests(ElasticTestCase):
|
||||||
|
|
||||||
q = question(title=u'Does this work?', save=True)
|
q = question(title=u'Does this work?', save=True)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(search.query(question_title__text='work').count(), 1)
|
eq_(search.query(question_title__match='work').count(), 1)
|
||||||
|
|
||||||
q.creator.delete()
|
q.creator.delete()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(search.query(question_title__text='work').count(), 0)
|
eq_(search.query(question_title__match='work').count(), 0)
|
||||||
|
|
||||||
def test_question_is_reindexed_on_username_change(self):
|
def test_question_is_reindexed_on_username_change(self):
|
||||||
search = QuestionMappingType.search()
|
search = QuestionMappingType.search()
|
||||||
|
@ -168,9 +168,9 @@ class QuestionUpdateTests(ElasticTestCase):
|
||||||
q = question(creator=u, title=u'Hello', save=True)
|
q = question(creator=u, title=u'Hello', save=True)
|
||||||
a = answer(creator=u, content=u'I love you', save=True)
|
a = answer(creator=u, content=u'I love you', save=True)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(search.query(question_title__text='hello')[0]['question_creator'],
|
eq_(search.query(question_title__match='hello')[0]['question_creator'],
|
||||||
u'dexter')
|
u'dexter')
|
||||||
query = search.query(question_answer_content__text='love')
|
query = search.query(question_answer_content__match='love')
|
||||||
eq_(query[0]['question_answer_creator'],
|
eq_(query[0]['question_answer_creator'],
|
||||||
[u'dexter'])
|
[u'dexter'])
|
||||||
|
|
||||||
|
@ -178,9 +178,9 @@ class QuestionUpdateTests(ElasticTestCase):
|
||||||
u.username = 'walter'
|
u.username = 'walter'
|
||||||
u.save()
|
u.save()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(search.query(question_title__text='hello')[0]['question_creator'],
|
eq_(search.query(question_title__match='hello')[0]['question_creator'],
|
||||||
u'walter')
|
u'walter')
|
||||||
query = search.query(question_answer_content__text='love')
|
query = search.query(question_answer_content__match='love')
|
||||||
eq_(query[0]['question_answer_creator'], [u'walter'])
|
eq_(query[0]['question_answer_creator'], [u'walter'])
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,8 +196,8 @@ class QuestionSearchTests(ElasticTestCase):
|
||||||
helpful=True).save()
|
helpful=True).save()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
result = QuestionMappingType.search().query(
|
result = QuestionMappingType.search().query(
|
||||||
question_title__text='LOLRUS',
|
question_title__match='LOLRUS',
|
||||||
question_content__text='LOLRUS')
|
question_content__match='LOLRUS')
|
||||||
assert result.count() > 0
|
assert result.count() > 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1593,9 +1593,9 @@ def _search_suggestions(request, text, locale, product_slugs):
|
||||||
results = []
|
results = []
|
||||||
try:
|
try:
|
||||||
# Search for relevant KB documents.
|
# Search for relevant KB documents.
|
||||||
query = dict(('%s__text' % field, text)
|
query = dict(('%s__match' % field, text)
|
||||||
for field in DocumentMappingType.get_query_fields())
|
for field in DocumentMappingType.get_query_fields())
|
||||||
query.update(dict(('%s__text_phrase' % field, text)
|
query.update(dict(('%s__match_phrase' % field, text)
|
||||||
for field in DocumentMappingType.get_query_fields()))
|
for field in DocumentMappingType.get_query_fields()))
|
||||||
query = es_query_with_analyzer(query, locale)
|
query = es_query_with_analyzer(query, locale)
|
||||||
filter = F()
|
filter = F()
|
||||||
|
@ -1624,9 +1624,9 @@ def _search_suggestions(request, text, locale, product_slugs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Search for relevant questions.
|
# Search for relevant questions.
|
||||||
query = dict(('%s__text' % field, text)
|
query = dict(('%s__match' % field, text)
|
||||||
for field in QuestionMappingType.get_query_fields())
|
for field in QuestionMappingType.get_query_fields())
|
||||||
query.update(dict(('%s__text_phrase' % field, text)
|
query.update(dict(('%s__match_phrase' % field, text)
|
||||||
for field in QuestionMappingType.get_query_fields()))
|
for field in QuestionMappingType.get_query_fields()))
|
||||||
|
|
||||||
max_age = int(time.time()) - settings.SEARCH_DEFAULT_MAX_QUESTION_AGE
|
max_age = int(time.time()) - settings.SEARCH_DEFAULT_MAX_QUESTION_AGE
|
||||||
|
|
|
@ -66,8 +66,8 @@ class AnalyzerMixin(object):
|
||||||
:arg key: is the field being searched
|
:arg key: is the field being searched
|
||||||
:arg val: Is a two-tupe of the text to query for and the name of
|
:arg val: Is a two-tupe of the text to query for and the name of
|
||||||
the analyzer to use.
|
the analyzer to use.
|
||||||
:arg action: is the type of query being performed, like text or
|
:arg action: is the type of query being performed, like match or
|
||||||
text_phrase
|
match_phrase
|
||||||
"""
|
"""
|
||||||
query, analyzer = val
|
query, analyzer = val
|
||||||
clause = {
|
clause = {
|
||||||
|
@ -85,13 +85,13 @@ class AnalyzerMixin(object):
|
||||||
|
|
||||||
return clause
|
return clause
|
||||||
|
|
||||||
def process_query_text_phrase_analyzer(self, key, val, action):
|
def process_query_match_phrase_analyzer(self, key, val, action):
|
||||||
"""A text phrase query that includes an analyzer."""
|
"""A match phrase query that includes an analyzer."""
|
||||||
return self._with_analyzer(key, val, 'text_phrase')
|
return self._with_analyzer(key, val, 'match_phrase')
|
||||||
|
|
||||||
def process_query_text_analyzer(self, key, val, action):
|
def process_query_match_analyzer(self, key, val, action):
|
||||||
"""A text query that includes an analyzer."""
|
"""A match query that includes an analyzer."""
|
||||||
return self._with_analyzer(key, val, 'text')
|
return self._with_analyzer(key, val, 'match')
|
||||||
|
|
||||||
|
|
||||||
class Sphilastic(S, AnalyzerMixin):
|
class Sphilastic(S, AnalyzerMixin):
|
||||||
|
|
|
@ -1123,16 +1123,16 @@ class TestAnalyzers(ElasticTestCase):
|
||||||
def test_query_analyzer_upgrader(self):
|
def test_query_analyzer_upgrader(self):
|
||||||
analyzer = 'snowball-english-synonyms'
|
analyzer = 'snowball-english-synonyms'
|
||||||
before = {
|
before = {
|
||||||
'document_title__text': 'foo',
|
'document_title__match': 'foo',
|
||||||
'document_locale__text': 'bar',
|
'document_locale__match': 'bar',
|
||||||
'document_title__text_phrase': 'baz',
|
'document_title__match_phrase': 'baz',
|
||||||
'document_locale__text_phrase': 'qux'
|
'document_locale__match_phrase': 'qux'
|
||||||
}
|
}
|
||||||
expected = {
|
expected = {
|
||||||
'document_title__text_analyzer': ('foo', analyzer),
|
'document_title__match_analyzer': ('foo', analyzer),
|
||||||
'document_locale__text': 'bar',
|
'document_locale__match': 'bar',
|
||||||
'document_title__text_phrase_analyzer': ('baz', analyzer),
|
'document_title__match_phrase_analyzer': ('baz', analyzer),
|
||||||
'document_locale__text_phrase': 'qux',
|
'document_locale__match_phrase': 'qux',
|
||||||
}
|
}
|
||||||
actual = es_utils.es_query_with_analyzer(before, 'en-US')
|
actual = es_utils.es_query_with_analyzer(before, 'en-US')
|
||||||
eq_(actual, expected)
|
eq_(actual, expected)
|
||||||
|
|
|
@ -323,8 +323,8 @@ def search(request, template=None):
|
||||||
|
|
||||||
# Text phrases in document titles and content get an extra
|
# Text phrases in document titles and content get an extra
|
||||||
# boost.
|
# boost.
|
||||||
document_title__text_phrase=10.0,
|
document_title__match_phrase=10.0,
|
||||||
document_content__text_phrase=8.0)
|
document_content__match_phrase=8.0)
|
||||||
|
|
||||||
# Apply sortby for advanced search of questions
|
# Apply sortby for advanced search of questions
|
||||||
if cleaned['w'] == constants.WHERE_SUPPORT:
|
if cleaned['w'] == constants.WHERE_SUPPORT:
|
||||||
|
@ -358,10 +358,10 @@ def search(request, template=None):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
query = {}
|
query = {}
|
||||||
# Create text and text_phrase queries for every field
|
# Create match and match_phrase queries for every field
|
||||||
# we want to search.
|
# we want to search.
|
||||||
for field in query_fields:
|
for field in query_fields:
|
||||||
for query_type in ['text', 'text_phrase']:
|
for query_type in ['match', 'match_phrase']:
|
||||||
query['%s__%s' % (field, query_type)] = cleaned_q
|
query['%s__%s' % (field, query_type)] = cleaned_q
|
||||||
|
|
||||||
# Transform the query to use locale aware analyzers.
|
# Transform the query to use locale aware analyzers.
|
||||||
|
@ -530,7 +530,7 @@ def suggestions(request):
|
||||||
site = Site.objects.get_current()
|
site = Site.objects.get_current()
|
||||||
locale = locale_or_default(request.LANGUAGE_CODE)
|
locale = locale_or_default(request.LANGUAGE_CODE)
|
||||||
try:
|
try:
|
||||||
query = dict(('%s__text' % field, term)
|
query = dict(('%s__match' % field, term)
|
||||||
for field in DocumentMappingType.get_query_fields())
|
for field in DocumentMappingType.get_query_fields())
|
||||||
# Upgrade the query to an analyzer-aware one.
|
# Upgrade the query to an analyzer-aware one.
|
||||||
query = es_utils.es_query_with_analyzer(query, locale)
|
query = es_utils.es_query_with_analyzer(query, locale)
|
||||||
|
@ -541,7 +541,7 @@ def suggestions(request):
|
||||||
.values_dict('document_title', 'url')
|
.values_dict('document_title', 'url')
|
||||||
.query(or_=query)[:5])
|
.query(or_=query)[:5])
|
||||||
|
|
||||||
query = dict(('%s__text' % field, term)
|
query = dict(('%s__match' % field, term)
|
||||||
for field in QuestionMappingType.get_query_fields())
|
for field in QuestionMappingType.get_query_fields())
|
||||||
question_s = (QuestionMappingType.search()
|
question_s = (QuestionMappingType.search()
|
||||||
.filter(question_has_helpful=True)
|
.filter(question_has_helpful=True)
|
||||||
|
|
|
@ -114,7 +114,7 @@ class DocumentUpdateTests(ElasticTestCase):
|
||||||
revision(document=doc, is_approved=True, save=True)
|
revision(document=doc, is_approved=True, save=True)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(DocumentMappingType.search().query(
|
eq_(DocumentMappingType.search().query(
|
||||||
document_title__text='wool').count(), 1)
|
document_title__match='wool').count(), 1)
|
||||||
|
|
||||||
# Now create a revision that is a redirect and make sure the
|
# Now create a revision that is a redirect and make sure the
|
||||||
# document is removed from the index.
|
# document is removed from the index.
|
||||||
|
@ -122,7 +122,7 @@ class DocumentUpdateTests(ElasticTestCase):
|
||||||
save=True)
|
save=True)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
eq_(DocumentMappingType.search().query(
|
eq_(DocumentMappingType.search().query(
|
||||||
document_title__text='wool').count(), 0)
|
document_title__match='wool').count(), 0)
|
||||||
|
|
||||||
def test_wiki_keywords(self):
|
def test_wiki_keywords(self):
|
||||||
"""Make sure updating keywords updates the index."""
|
"""Make sure updating keywords updates the index."""
|
||||||
|
|
Загрузка…
Ссылка в новой задаче