Fix Elasticsearch7 backend to work on pre-7.15 library versions

Fixes #7920. Check library version and only patch backend classes with the updated API calls if it's >=7.15.
pull/10918/head
Matt Westcott 2023-09-18 22:19:20 +01:00 zatwierdzone przez Matt Westcott
rodzic b60828ac47
commit 9372cb12e2
3 zmienionych plików z 96 dodań i 31 usunięć

Wyświetl plik

@ -1,5 +1,6 @@
from copy import deepcopy from copy import deepcopy
from elasticsearch import VERSION as ELASTICSEARCH_VERSION
from elasticsearch import NotFoundError from elasticsearch import NotFoundError
from elasticsearch.helpers import bulk from elasticsearch.helpers import bulk
@ -13,6 +14,8 @@ from wagtail.search.backends.elasticsearch6 import (
) )
from wagtail.search.index import class_is_indexed from wagtail.search.index import class_is_indexed
use_new_elasticsearch_api = ELASTICSEARCH_VERSION >= (7, 15)
class Elasticsearch7Mapping(Elasticsearch6Mapping): class Elasticsearch7Mapping(Elasticsearch6Mapping):
def get_mapping(self): def get_mapping(self):
@ -21,17 +24,19 @@ class Elasticsearch7Mapping(Elasticsearch6Mapping):
class Elasticsearch7Index(Elasticsearch6Index): class Elasticsearch7Index(Elasticsearch6Index):
def put(self): if use_new_elasticsearch_api:
self.es.indices.create(index=self.name, **self.backend.settings)
def delete(self): def put(self):
try: self.es.indices.create(index=self.name, **self.backend.settings)
self.es.indices.delete(index=self.name)
except NotFoundError:
pass
def refresh(self): def delete(self):
self.es.indices.refresh(index=self.name) try:
self.es.indices.delete(index=self.name)
except NotFoundError:
pass
def refresh(self):
self.es.indices.refresh(index=self.name)
def add_model(self, model): def add_model(self, model):
# Get mapping # Get mapping
@ -40,20 +45,36 @@ class Elasticsearch7Index(Elasticsearch6Index):
# Put mapping # Put mapping
self.es.indices.put_mapping(index=self.name, body=mapping.get_mapping()) self.es.indices.put_mapping(index=self.name, body=mapping.get_mapping())
def add_item(self, item): if use_new_elasticsearch_api:
# Make sure the object can be indexed
if not class_is_indexed(item.__class__):
return
# Get mapping def add_item(self, item):
mapping = self.mapping_class(item.__class__) # Make sure the object can be indexed
if not class_is_indexed(item.__class__):
return
# Add document to index # Get mapping
self.es.index( mapping = self.mapping_class(item.__class__)
index=self.name,
document=mapping.get_document(item), # Add document to index
id=mapping.get_document_id(item), self.es.index(
) index=self.name,
document=mapping.get_document(item),
id=mapping.get_document_id(item),
)
else:
def add_item(self, item):
# Make sure the object can be indexed
if not class_is_indexed(item.__class__):
return
# Get mapping
mapping = self.mapping_class(item.__class__)
# Add document to index
self.es.index(
self.name, mapping.get_document(item), id=mapping.get_document_id(item)
)
def add_items(self, model, items): def add_items(self, model, items):
if not class_is_indexed(model): if not class_is_indexed(model):
@ -93,10 +114,12 @@ class Elasticsearch7SearchQueryCompiler(Elasticsearch6SearchQueryCompiler):
class Elasticsearch7SearchResults(Elasticsearch6SearchResults): class Elasticsearch7SearchResults(Elasticsearch6SearchResults):
def _backend_do_search(self, body, **kwargs): if use_new_elasticsearch_api:
# As of Elasticsearch 7, the 'body' parameter is deprecated; instead, the top-level
# keys of the body dict are now kwargs in their own right def _backend_do_search(self, body, **kwargs):
return self.backend.es.search(**body, **kwargs) # As of Elasticsearch 7.15, the 'body' parameter is deprecated; instead, the top-level
# keys of the body dict are now kwargs in their own right
return self.backend.es.search(**body, **kwargs)
class Elasticsearch7AutocompleteQueryCompiler( class Elasticsearch7AutocompleteQueryCompiler(

Wyświetl plik

@ -1,4 +1,5 @@
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from elasticsearch import NotFoundError
from wagtail.search.backends.elasticsearch7 import ( from wagtail.search.backends.elasticsearch7 import (
Elasticsearch7AutocompleteQueryCompiler, Elasticsearch7AutocompleteQueryCompiler,
@ -8,6 +9,7 @@ from wagtail.search.backends.elasticsearch7 import (
Elasticsearch7SearchQueryCompiler, Elasticsearch7SearchQueryCompiler,
Elasticsearch7SearchResults, Elasticsearch7SearchResults,
) )
from wagtail.search.index import class_is_indexed
class Elasticsearch8Mapping(Elasticsearch7Mapping): class Elasticsearch8Mapping(Elasticsearch7Mapping):
@ -15,6 +17,18 @@ class Elasticsearch8Mapping(Elasticsearch7Mapping):
class Elasticsearch8Index(Elasticsearch7Index): class Elasticsearch8Index(Elasticsearch7Index):
def put(self):
self.es.indices.create(index=self.name, **self.backend.settings)
def delete(self):
try:
self.es.indices.delete(index=self.name)
except NotFoundError:
pass
def refresh(self):
self.es.indices.refresh(index=self.name)
def add_model(self, model): def add_model(self, model):
# Get mapping # Get mapping
mapping = self.mapping_class(model) mapping = self.mapping_class(model)
@ -22,13 +36,31 @@ class Elasticsearch8Index(Elasticsearch7Index):
# Put mapping # Put mapping
self.es.indices.put_mapping(index=self.name, **mapping.get_mapping()) self.es.indices.put_mapping(index=self.name, **mapping.get_mapping())
def add_item(self, item):
# Make sure the object can be indexed
if not class_is_indexed(item.__class__):
return
# Get mapping
mapping = self.mapping_class(item.__class__)
# Add document to index
self.es.index(
index=self.name,
document=mapping.get_document(item),
id=mapping.get_document_id(item),
)
class Elasticsearch8SearchQueryCompiler(Elasticsearch7SearchQueryCompiler): class Elasticsearch8SearchQueryCompiler(Elasticsearch7SearchQueryCompiler):
mapping_class = Elasticsearch8Mapping mapping_class = Elasticsearch8Mapping
class Elasticsearch8SearchResults(Elasticsearch7SearchResults): class Elasticsearch8SearchResults(Elasticsearch7SearchResults):
pass def _backend_do_search(self, body, **kwargs):
# As of Elasticsearch 7.15, the 'body' parameter is deprecated; instead, the top-level
# keys of the body dict are now kwargs in their own right
return self.backend.es.search(**body, **kwargs)
class Elasticsearch8AutocompleteQueryCompiler(Elasticsearch7AutocompleteQueryCompiler): class Elasticsearch8AutocompleteQueryCompiler(Elasticsearch7AutocompleteQueryCompiler):

Wyświetl plik

@ -20,6 +20,16 @@ except ImportError:
ELASTICSEARCH_VERSION = (0, 0, 0) ELASTICSEARCH_VERSION = (0, 0, 0)
use_new_elasticsearch_api = ELASTICSEARCH_VERSION >= (7, 15)
if use_new_elasticsearch_api:
search_query_kwargs = {
"query": "QUERY",
}
else:
search_query_kwargs = {"body": {"query": "QUERY"}}
@unittest.skipIf(ELASTICSEARCH_VERSION[0] != 7, "Elasticsearch 7 required") @unittest.skipIf(ELASTICSEARCH_VERSION[0] != 7, "Elasticsearch 7 required")
class TestElasticsearch7SearchBackend(ElasticsearchCommonSearchBackendTests, TestCase): class TestElasticsearch7SearchBackend(ElasticsearchCommonSearchBackendTests, TestCase):
backend_path = "wagtail.search.backends.elasticsearch7" backend_path = "wagtail.search.backends.elasticsearch7"
@ -915,12 +925,12 @@ class TestElasticsearch7SearchResults(TestCase):
list(results) # Performs search list(results) # Performs search
search.assert_any_call( search.assert_any_call(
query="QUERY",
_source=False, _source=False,
stored_fields="pk", stored_fields="pk",
index="wagtail__searchtests_book", index="wagtail__searchtests_book",
scroll="2m", scroll="2m",
size=100, size=100,
**search_query_kwargs,
) )
@mock.patch("elasticsearch.Elasticsearch.search") @mock.patch("elasticsearch.Elasticsearch.search")
@ -933,11 +943,11 @@ class TestElasticsearch7SearchResults(TestCase):
search.assert_any_call( search.assert_any_call(
from_=10, from_=10,
query="QUERY",
_source=False, _source=False,
stored_fields="pk", stored_fields="pk",
index="wagtail__searchtests_book", index="wagtail__searchtests_book",
size=1, size=1,
**search_query_kwargs,
) )
@mock.patch("elasticsearch.Elasticsearch.search") @mock.patch("elasticsearch.Elasticsearch.search")
@ -949,11 +959,11 @@ class TestElasticsearch7SearchResults(TestCase):
search.assert_any_call( search.assert_any_call(
from_=1, from_=1,
query="QUERY",
_source=False, _source=False,
stored_fields="pk", stored_fields="pk",
index="wagtail__searchtests_book", index="wagtail__searchtests_book",
size=3, size=3,
**search_query_kwargs,
) )
@mock.patch("elasticsearch.Elasticsearch.search") @mock.patch("elasticsearch.Elasticsearch.search")
@ -965,11 +975,11 @@ class TestElasticsearch7SearchResults(TestCase):
search.assert_any_call( search.assert_any_call(
from_=10, from_=10,
query="QUERY",
_source=False, _source=False,
stored_fields="pk", stored_fields="pk",
index="wagtail__searchtests_book", index="wagtail__searchtests_book",
size=10, size=10,
**search_query_kwargs,
) )
@mock.patch("elasticsearch.Elasticsearch.search") @mock.patch("elasticsearch.Elasticsearch.search")
@ -982,11 +992,11 @@ class TestElasticsearch7SearchResults(TestCase):
search.assert_any_call( search.assert_any_call(
from_=20, from_=20,
query="QUERY",
_source=False, _source=False,
stored_fields="pk", stored_fields="pk",
index="wagtail__searchtests_book", index="wagtail__searchtests_book",
size=1, size=1,
**search_query_kwargs,
) )
@mock.patch("elasticsearch.Elasticsearch.search") @mock.patch("elasticsearch.Elasticsearch.search")