class TestElasticSearchMapping(TestCase):
    def assertDictEqual(self, a, b):
        default = JSONSerializer().default
        self.assertEqual(json.dumps(a, sort_keys=True, default=default), json.dumps(b, sort_keys=True, default=default))

    def setUp(self):
        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTest)

        # Create ES document
        self.obj = models.SearchTest(title="Hello")
        self.obj.save()

    def test_get_document_type(self):
        self.assertEqual(self.es_mapping.get_document_type(), 'searchtests_searchtest')

    def test_get_mapping(self):
        # Build mapping
        mapping = self.es_mapping.get_mapping()

        # Check
        expected_result = {
            'searchtests_searchtest': {
                'properties': {
                    'pk': {'index': 'not_analyzed', 'type': 'string', 'store': 'yes', 'include_in_all': False},
                    'content_type': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    '_partials': {'index_analyzer': 'edgengram_analyzer', 'include_in_all': False, 'type': 'string'},
                    'live_filter': {'index': 'not_analyzed', 'type': 'boolean', 'include_in_all': False},
                    'published_date_filter': {'index': 'not_analyzed', 'type': 'date', 'include_in_all': False},
                    'title': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},
                    'title_filter': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    'content': {'type': 'string', 'include_in_all': True},
                    'callable_indexed_field': {'type': 'string', 'include_in_all': True}
                }
            }
        }

        self.assertDictEqual(mapping, expected_result)

    def test_get_document_id(self):
        self.assertEqual(self.es_mapping.get_document_id(self.obj), 'searchtests_searchtest:' + str(self.obj.pk))

    def test_get_document(self):
        # Get document
        document = self.es_mapping.get_document(self.obj)

        # Check
        expected_result = {
            'pk': str(self.obj.pk),
            'content_type': 'searchtests_searchtest',
            '_partials': ['Hello'],
            'live_filter': False,
            'published_date_filter': None,
            'title': 'Hello',
            'title_filter': 'Hello',
            'callable_indexed_field': 'Callable',
            'content': '',
        }

        self.assertDictEqual(document, expected_result)
    def setUp(self):
        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTestChild)

        # Create ES document
        self.obj = models.SearchTestChild(title="Hello", subtitle="World", page_id=1)
        self.obj.save()
        self.obj.tags.add("a tag")
    def setUp(self):
        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTest)

        # Create ES document
        self.obj = models.SearchTest(title="Hello")
        self.obj.save()
        self.obj.tags.add("a tag")
    def setUp(self):
        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTest)

        # Create ES document
        self.obj = models.SearchTest(title="Hello")
        self.obj.save()
    def setUp(self):
        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTestChild)

        # Create ES document
        self.obj = models.SearchTestChild(title="Hello", subtitle="World")
        self.obj.save()
    def setUp(self):
        # Import using a try-catch block to prevent crashes if the elasticsearch-py
        # module is not installed
        try:
            from wagtail.wagtailsearch.backends.elasticsearch import ElasticSearchMapping
            from elasticsearch.serializer import JSONSerializer
        except ImportError:
            raise unittest.SkipTest("elasticsearch-py not installed")

        self.JSONSerializer = JSONSerializer

        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTestChild)

        # Create ES document
        self.obj = models.SearchTestChild(title="Hello", subtitle="World")
        self.obj.save()
    def test_add_model(self):
        self.rebuilder.start()

        # Add model
        self.rebuilder.add_model(models.SearchTest)

        # Check the mapping went into Elasticsearch correctly
        mapping = ElasticSearchMapping(models.SearchTest)
        response = self.es.indices.get_mapping(self.backend.es_index, mapping.get_document_type())

        # Make some minor tweaks to the mapping so it matches what is in ES
        # These are generally minor issues with the way Wagtail is generating the mapping that are being cleaned up by Elasticsearch
        # TODO: Would be nice to fix these
        expected_mapping = mapping.get_mapping()
        expected_mapping['searchtests_searchtest']['properties']['pk']['store'] = True
        expected_mapping['searchtests_searchtest']['properties']['live_filter'].pop('index')
        expected_mapping['searchtests_searchtest']['properties']['live_filter'].pop('include_in_all')
        expected_mapping['searchtests_searchtest']['properties']['published_date_filter']['format'] = 'dateOptionalTime'
        expected_mapping['searchtests_searchtest']['properties']['published_date_filter'].pop('index')

        self.assertDictEqual(expected_mapping, response[self.backend.es_index]['mappings'])
    def test_add_model(self):
        self.rebuilder.start()

        # Add model
        self.rebuilder.add_model(models.SearchTest)

        # Check the mapping went into Elasticsearch correctly
        mapping = ElasticSearchMapping(models.SearchTest)
        response = self.es.indices.get_mapping(self.backend.es_index, mapping.get_document_type())

        # Make some minor tweaks to the mapping so it matches what is in ES
        # These are generally minor issues with the way Wagtail is
        # generating the mapping that are being cleaned up by Elasticsearch
        # TODO: Would be nice to fix these
        expected_mapping = mapping.get_mapping()
        expected_mapping['searchtests_searchtest']['properties']['pk']['store'] = True
        expected_mapping['searchtests_searchtest']['properties']['live_filter'].pop('index')
        expected_mapping['searchtests_searchtest']['properties']['live_filter'].pop('include_in_all')
        expected_mapping['searchtests_searchtest']['properties']['published_date_filter']['format'] = \
            'dateOptionalTime'
        expected_mapping['searchtests_searchtest']['properties']['published_date_filter'].pop('index')

        self.assertDictEqual(expected_mapping, response[self.backend.es_index]['mappings'])
    def setUp(self):
        # Import using a try-catch block to prevent crashes if the elasticsearch-py
        # module is not installed
        try:
            from wagtail.wagtailsearch.backends.elasticsearch import ElasticSearchMapping
            from elasticsearch.serializer import JSONSerializer
        except ImportError:
            raise unittest.SkipTest("elasticsearch-py not installed")

        self.JSONSerializer = JSONSerializer

        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTestChild)

        # Create ES document
        self.obj = models.SearchTestChild(title="Hello", subtitle="World")
        self.obj.save()
Example #10
0
    def related_articles(self):
        if not self.pk:
            # In preview mode
            return []

        max_results = getattr(settings, "MAX_RELATED_RESULTS", 4)
        es_backend = get_search_backend()
        mapping = ElasticSearchMapping(self.__class__)

        minimal_locations = ""
        if (self.get_minimal_locations()):
            minimal_locations = self.get_minimal_locations()

        state_locations = ""
        if (self.get_state_from_locations()):
            state_locations = self.get_state_from_locations()

        authors_of_article = ""

        if self.authors:
            for author in self.authors.all():
                authors_of_article += author.name

        query = {
            "track_scores": "true",
            "query": {
                "bool": {
                    "must": [
                        {"match": {"language": self.language}},
                        {"term": {"live_filter": "true"}}
                    ],
                    "must_not": [
                        {"term": {"title_filter": self.title}}

                    ],
                    "should": [
                        {
                            "multi_match": {
                                "fields": "get_authors_or_photographers_filter",
                                "query": ["" + authors_of_article + ""]
                            }

                        },
                        {
                            "multi_match": {
                                "fields": "get_authors",
                                "query": ["" + authors_of_article + ""]
                            }

                        },
                        {
                            "multi_match": {
                                "fields": "get_minimal_locations_filter",
                                "query":minimal_locations
                            }
                        },
                        {
                            "multi_match":{
                                "fields":"get_state_from_locations_filter",
                                "query":state_locations
                            }

                        },
                        {
                            "match":{
                                "title":self.title
                            }
                        }
                    ],
                    "minimum_should_match": 1
                }
            },
            "sort": [
                {"_score": {"order": "desc"}},
                {"get_authors":{"order": "desc"}},
                {"first_published_at_filter": "desc"}
            ]
        }


        try:
            mlt = es_backend.es.search(
                index=es_backend.index_name,
                doc_type=mapping.get_document_type(),
                body=query
            )
        except ConnectionError:
            return []
        # Get pks from results
        pks = [hit['_source']['pk'] for hit in mlt['hits']['hits']][:max_results]

        # Initialise results dictionary
        results = dict((str(pk), None) for pk in pks)

        # Find objects in database and add them to dict
        queryset = self._default_manager.filter(pk__in=pks)
        for obj in queryset:
            results[str(obj.pk)] = obj

        # Return results in order given by ElasticSearch
        return [results[str(pk)] for pk in pks if results[str(pk)]]
class TestElasticSearchMapping(TestCase):
    def assertDictEqual(self, a, b):
        default = self.JSONSerializer().default
        self.assertEqual(json.dumps(a, sort_keys=True, default=default), json.dumps(b, sort_keys=True, default=default))

    def setUp(self):
        # Import using a try-catch block to prevent crashes if the elasticsearch-py
        # module is not installed
        try:
            from wagtail.wagtailsearch.backends.elasticsearch import ElasticSearchMapping
            from elasticsearch.serializer import JSONSerializer
        except ImportError:
            raise unittest.SkipTest("elasticsearch-py not installed")

        self.JSONSerializer = JSONSerializer

        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTest)

        # Create ES document
        self.obj = models.SearchTest(title="Hello")
        self.obj.save()

    def test_get_document_type(self):
        self.assertEqual(self.es_mapping.get_document_type(), 'searchtests_searchtest')

    def test_get_mapping(self):
        # Build mapping
        mapping = self.es_mapping.get_mapping()

        # Check
        expected_result = {
            'searchtests_searchtest': {
                'properties': {
                    'pk': {'index': 'not_analyzed', 'type': 'string', 'store': 'yes', 'include_in_all': False},
                    'content_type': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    '_partials': {'index_analyzer': 'edgengram_analyzer', 'include_in_all': False, 'type': 'string'},
                    'live_filter': {'index': 'not_analyzed', 'type': 'boolean', 'include_in_all': False},
                    'published_date_filter': {'index': 'not_analyzed', 'type': 'date', 'include_in_all': False},
                    'title': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},
                    'title_filter': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    'content': {'type': 'string', 'include_in_all': True},
                    'callable_indexed_field': {'type': 'string', 'include_in_all': True}
                }
            }
        }

        self.assertDictEqual(mapping, expected_result)

    def test_get_document_id(self):
        self.assertEqual(self.es_mapping.get_document_id(self.obj), 'searchtests_searchtest:' + str(self.obj.pk))

    def test_get_document(self):
        # Get document
        document = self.es_mapping.get_document(self.obj)

        # Check
        expected_result = {
            'pk': str(self.obj.pk),
            'content_type': 'searchtests_searchtest',
            '_partials': ['Hello'],
            'live_filter': False,
            'published_date_filter': None,
            'title': 'Hello',
            'title_filter': 'Hello',
            'callable_indexed_field': 'Callable',
            'content': '',
        }

        self.assertDictEqual(document, expected_result)
class TestElasticSearchMappingInheritance(TestCase):
    def assertDictEqual(self, a, b):
        default = self.JSONSerializer().default
        self.assertEqual(json.dumps(a, sort_keys=True, default=default), json.dumps(b, sort_keys=True, default=default))

    def setUp(self):
        # Import using a try-catch block to prevent crashes if the elasticsearch-py
        # module is not installed
        try:
            from wagtail.wagtailsearch.backends.elasticsearch import ElasticSearchMapping
            from elasticsearch.serializer import JSONSerializer
        except ImportError:
            raise unittest.SkipTest("elasticsearch-py not installed")

        self.JSONSerializer = JSONSerializer

        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTestChild)

        # Create ES document
        self.obj = models.SearchTestChild(title="Hello", subtitle="World")
        self.obj.save()

    def test_get_document_type(self):
        self.assertEqual(self.es_mapping.get_document_type(), 'searchtests_searchtest_searchtests_searchtestchild')

    def test_get_mapping(self):
        # Build mapping
        mapping = self.es_mapping.get_mapping()

        # Check
        expected_result = {
            'searchtests_searchtest_searchtests_searchtestchild': {
                'properties': {
                    # New
                    'extra_content': {'type': 'string', 'include_in_all': True},
                    'subtitle': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},

                    # Inherited
                    'pk': {'index': 'not_analyzed', 'type': 'string', 'store': 'yes', 'include_in_all': False},
                    'content_type': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    '_partials': {'index_analyzer': 'edgengram_analyzer', 'include_in_all': False, 'type': 'string'},
                    'live_filter': {'index': 'not_analyzed', 'type': 'boolean', 'include_in_all': False},
                    'published_date_filter': {'index': 'not_analyzed', 'type': 'date', 'include_in_all': False},
                    'title': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},
                    'title_filter': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    'content': {'type': 'string', 'include_in_all': True},
                    'callable_indexed_field': {'type': 'string', 'include_in_all': True}
                }
            }
        }

        self.assertDictEqual(mapping, expected_result)

    def test_get_document_id(self):
        # This must be tests_searchtest instead of 'tests_searchtest_tests_searchtestchild'
        # as it uses the contents base content type name.
        # This prevents the same object being accidentally indexed twice.
        self.assertEqual(self.es_mapping.get_document_id(self.obj), 'searchtests_searchtest:' + str(self.obj.pk))

    def test_get_document(self):
        # Build document
        document = self.es_mapping.get_document(self.obj)

        # Sort partials
        if '_partials' in document:
            document['_partials'].sort()

        # Check
        expected_result = {
            # New
            'extra_content': '',
            'subtitle': 'World',

            # Changed
            'content_type': 'searchtests_searchtest_searchtests_searchtestchild',

            # Inherited
            'pk': str(self.obj.pk),
            '_partials': ['Hello', 'World'],
            'live_filter': False,
            'published_date_filter': None,
            'title': 'Hello',
            'title_filter': 'Hello',
            'callable_indexed_field': 'Callable',
            'content': '',
        }

        self.assertDictEqual(document, expected_result)
class TestElasticSearchMapping(TestCase):
    def assertDictEqual(self, a, b):
        default = JSONSerializer().default
        self.assertEqual(
            json.dumps(a, sort_keys=True, default=default), json.dumps(b, sort_keys=True, default=default)
        )

    def setUp(self):
        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTest)

        # Create ES document
        self.obj = models.SearchTest(title="Hello")
        self.obj.save()
        self.obj.tags.add("a tag")

    def test_get_document_type(self):
        self.assertEqual(self.es_mapping.get_document_type(), 'searchtests_searchtest')

    def test_get_mapping(self):
        # Build mapping
        mapping = self.es_mapping.get_mapping()

        # Check
        expected_result = {
            'searchtests_searchtest': {
                'properties': {
                    'pk': {'index': 'not_analyzed', 'type': 'string', 'store': 'yes', 'include_in_all': False},
                    'content_type': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    '_partials': {'index_analyzer': 'edgengram_analyzer', 'include_in_all': False, 'type': 'string'},
                    'live_filter': {'index': 'not_analyzed', 'type': 'boolean', 'include_in_all': False},
                    'published_date_filter': {'index': 'not_analyzed', 'type': 'date', 'include_in_all': False},
                    'title': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},
                    'title_filter': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    'content': {'type': 'string', 'include_in_all': True},
                    'callable_indexed_field': {'type': 'string', 'include_in_all': True},
                    'tags': {
                        'type': 'nested',
                        'properties': {
                            'name': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},
                            'slug_filter': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                        }
                    },
                }
            }
        }

        self.assertDictEqual(mapping, expected_result)

    def test_get_document_id(self):
        self.assertEqual(self.es_mapping.get_document_id(self.obj), 'searchtests_searchtest:' + str(self.obj.pk))

    def test_get_document(self):
        # Get document
        document = self.es_mapping.get_document(self.obj)

        # Sort partials
        if '_partials' in document:
            document['_partials'].sort()

        # Check
        expected_result = {
            'pk': str(self.obj.pk),
            'content_type': 'searchtests_searchtest',
            '_partials': ['Hello', 'a tag'],
            'live_filter': False,
            'published_date_filter': None,
            'title': 'Hello',
            'title_filter': 'Hello',
            'callable_indexed_field': 'Callable',
            'content': '',
            'tags': [
                {
                    'name': 'a tag',
                    'slug_filter': 'a-tag',
                }
            ],
        }

        self.assertDictEqual(document, expected_result)
class TestElasticSearchMappingInheritance(TestCase):
    def assertDictEqual(self, a, b):
        default = self.JSONSerializer().default
        self.assertEqual(json.dumps(a, sort_keys=True, default=default),
                         json.dumps(b, sort_keys=True, default=default))

    def setUp(self):
        # Import using a try-catch block to prevent crashes if the elasticsearch-py
        # module is not installed
        try:
            from wagtail.wagtailsearch.backends.elasticsearch import ElasticSearchMapping
            from elasticsearch.serializer import JSONSerializer
        except ImportError:
            raise unittest.SkipTest("elasticsearch-py not installed")

        self.JSONSerializer = JSONSerializer

        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTestChild)

        # Create ES document
        self.obj = models.SearchTestChild(title="Hello", subtitle="World")
        self.obj.save()

    def test_get_document_type(self):
        self.assertEqual(self.es_mapping.get_document_type(),
                         'searchtests_searchtest_searchtests_searchtestchild')

    def test_get_mapping(self):
        # Build mapping
        mapping = self.es_mapping.get_mapping()

        # Check
        expected_result = {
            'searchtests_searchtest_searchtests_searchtestchild': {
                'properties': {
                    # New
                    'extra_content': {
                        'type': 'string',
                        'include_in_all': True
                    },
                    'subtitle': {
                        'type': 'string',
                        'include_in_all': True,
                        'index_analyzer': 'edgengram_analyzer'
                    },

                    # Inherited
                    'pk': {
                        'index': 'not_analyzed',
                        'type': 'string',
                        'store': 'yes',
                        'include_in_all': False
                    },
                    'content_type': {
                        'index': 'not_analyzed',
                        'type': 'string',
                        'include_in_all': False
                    },
                    '_partials': {
                        'index_analyzer': 'edgengram_analyzer',
                        'include_in_all': False,
                        'type': 'string'
                    },
                    'live_filter': {
                        'index': 'not_analyzed',
                        'type': 'boolean',
                        'include_in_all': False
                    },
                    'published_date_filter': {
                        'index': 'not_analyzed',
                        'type': 'date',
                        'include_in_all': False
                    },
                    'title': {
                        'type': 'string',
                        'include_in_all': True,
                        'index_analyzer': 'edgengram_analyzer'
                    },
                    'title_filter': {
                        'index': 'not_analyzed',
                        'type': 'string',
                        'include_in_all': False
                    },
                    'content': {
                        'type': 'string',
                        'include_in_all': True
                    },
                    'callable_indexed_field': {
                        'type': 'string',
                        'include_in_all': True
                    }
                }
            }
        }

        self.assertDictEqual(mapping, expected_result)

    def test_get_document_id(self):
        # This must be tests_searchtest instead of 'tests_searchtest_tests_searchtestchild'
        # as it uses the contents base content type name.
        # This prevents the same object being accidentally indexed twice.
        self.assertEqual(self.es_mapping.get_document_id(self.obj),
                         'searchtests_searchtest:' + str(self.obj.pk))

    def test_get_document(self):
        # Build document
        document = self.es_mapping.get_document(self.obj)

        # Sort partials
        if '_partials' in document:
            document['_partials'].sort()

        # Check
        expected_result = {
            # New
            'extra_content': '',
            'subtitle': 'World',

            # Changed
            'content_type':
            'searchtests_searchtest_searchtests_searchtestchild',

            # Inherited
            'pk': str(self.obj.pk),
            '_partials': ['Hello', 'World'],
            'live_filter': False,
            'published_date_filter': None,
            'title': 'Hello',
            'title_filter': 'Hello',
            'callable_indexed_field': 'Callable',
            'content': '',
        }

        self.assertDictEqual(document, expected_result)
class TestElasticSearchMapping(TestCase):
    def assertDictEqual(self, a, b):
        default = self.JSONSerializer().default
        self.assertEqual(json.dumps(a, sort_keys=True, default=default),
                         json.dumps(b, sort_keys=True, default=default))

    def setUp(self):
        # Import using a try-catch block to prevent crashes if the elasticsearch-py
        # module is not installed
        try:
            from wagtail.wagtailsearch.backends.elasticsearch import ElasticSearchMapping
            from elasticsearch.serializer import JSONSerializer
        except ImportError:
            raise unittest.SkipTest("elasticsearch-py not installed")

        self.JSONSerializer = JSONSerializer

        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTest)

        # Create ES document
        self.obj = models.SearchTest(title="Hello")
        self.obj.save()

    def test_get_document_type(self):
        self.assertEqual(self.es_mapping.get_document_type(),
                         'searchtests_searchtest')

    def test_get_mapping(self):
        # Build mapping
        mapping = self.es_mapping.get_mapping()

        # Check
        expected_result = {
            'searchtests_searchtest': {
                'properties': {
                    'pk': {
                        'index': 'not_analyzed',
                        'type': 'string',
                        'store': 'yes',
                        'include_in_all': False
                    },
                    'content_type': {
                        'index': 'not_analyzed',
                        'type': 'string',
                        'include_in_all': False
                    },
                    '_partials': {
                        'index_analyzer': 'edgengram_analyzer',
                        'include_in_all': False,
                        'type': 'string'
                    },
                    'live_filter': {
                        'index': 'not_analyzed',
                        'type': 'boolean',
                        'include_in_all': False
                    },
                    'published_date_filter': {
                        'index': 'not_analyzed',
                        'type': 'date',
                        'include_in_all': False
                    },
                    'title': {
                        'type': 'string',
                        'include_in_all': True,
                        'index_analyzer': 'edgengram_analyzer'
                    },
                    'title_filter': {
                        'index': 'not_analyzed',
                        'type': 'string',
                        'include_in_all': False
                    },
                    'content': {
                        'type': 'string',
                        'include_in_all': True
                    },
                    'callable_indexed_field': {
                        'type': 'string',
                        'include_in_all': True
                    }
                }
            }
        }

        self.assertDictEqual(mapping, expected_result)

    def test_get_document_id(self):
        self.assertEqual(self.es_mapping.get_document_id(self.obj),
                         'searchtests_searchtest:' + str(self.obj.pk))

    def test_get_document(self):
        # Get document
        document = self.es_mapping.get_document(self.obj)

        # Check
        expected_result = {
            'pk': str(self.obj.pk),
            'content_type': 'searchtests_searchtest',
            '_partials': ['Hello'],
            'live_filter': False,
            'published_date_filter': None,
            'title': 'Hello',
            'title_filter': 'Hello',
            'callable_indexed_field': 'Callable',
            'content': '',
        }

        self.assertDictEqual(document, expected_result)
class TestElasticSearchMappingInheritance(TestCase):
    def assertDictEqual(self, a, b):
        default = JSONSerializer().default
        self.assertEqual(
            json.dumps(a, sort_keys=True, default=default), json.dumps(b, sort_keys=True, default=default)
        )

    def setUp(self):
        # Create ES mapping
        self.es_mapping = ElasticSearchMapping(models.SearchTestChild)

        # Create ES document
        self.obj = models.SearchTestChild(title="Hello", subtitle="World", page_id=1)
        self.obj.save()
        self.obj.tags.add("a tag")

    def test_get_document_type(self):
        self.assertEqual(self.es_mapping.get_document_type(), 'searchtests_searchtest_searchtests_searchtestchild')

    def test_get_mapping(self):
        # Build mapping
        mapping = self.es_mapping.get_mapping()

        # Check
        expected_result = {
            'searchtests_searchtest_searchtests_searchtestchild': {
                'properties': {
                    # New
                    'extra_content': {'type': 'string', 'include_in_all': True},
                    'subtitle': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},
                    'page': {
                        'type': 'nested',
                        'properties': {
                            'title': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},
                            'search_description': {'type': 'string', 'include_in_all': True},
                            'live_filter': {'index': 'not_analyzed', 'type': 'boolean', 'include_in_all': False},
                        }
                    },

                    # Inherited
                    'pk': {'index': 'not_analyzed', 'type': 'string', 'store': 'yes', 'include_in_all': False},
                    'content_type': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    '_partials': {'index_analyzer': 'edgengram_analyzer', 'include_in_all': False, 'type': 'string'},
                    'live_filter': {'index': 'not_analyzed', 'type': 'boolean', 'include_in_all': False},
                    'published_date_filter': {'index': 'not_analyzed', 'type': 'date', 'include_in_all': False},
                    'title': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},
                    'title_filter': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                    'content': {'type': 'string', 'include_in_all': True},
                    'callable_indexed_field': {'type': 'string', 'include_in_all': True},
                    'tags': {
                        'type': 'nested',
                        'properties': {
                            'name': {'type': 'string', 'include_in_all': True, 'index_analyzer': 'edgengram_analyzer'},
                            'slug_filter': {'index': 'not_analyzed', 'type': 'string', 'include_in_all': False},
                        }
                    },
                }
            }
        }

        self.assertDictEqual(mapping, expected_result)

    def test_get_document_id(self):
        # This must be tests_searchtest instead of 'tests_searchtest_tests_searchtestchild'
        # as it uses the contents base content type name.
        # This prevents the same object being accidentally indexed twice.
        self.assertEqual(self.es_mapping.get_document_id(self.obj), 'searchtests_searchtest:' + str(self.obj.pk))

    def test_get_document(self):
        # Build document
        document = self.es_mapping.get_document(self.obj)

        # Sort partials
        if '_partials' in document:
            document['_partials'].sort()

        # Check
        expected_result = {
            # New
            'extra_content': '',
            'subtitle': 'World',
            'page': {
                'title': 'Root',
                'search_description': '',
                'live_filter': True,
            },

            # Changed
            'content_type': 'searchtests_searchtest_searchtests_searchtestchild',

            # Inherited
            'pk': str(self.obj.pk),
            '_partials': ['Hello', 'Root', 'World', 'a tag'],
            'live_filter': False,
            'published_date_filter': None,
            'title': 'Hello',
            'title_filter': 'Hello',
            'callable_indexed_field': 'Callable',
            'content': '',
            'tags': [
                {
                    'name': 'a tag',
                    'slug_filter': 'a-tag',
                }
            ],
        }

        self.assertDictEqual(document, expected_result)
Example #17
0
    def related_articles(self):
        if not self.pk:
            # In preview mode
            return []
        max_results = getattr(settings, "MAX_RELATED_RESULTS", 4)
        es_backend = get_search_backend()
        mapping = ElasticSearchMapping(self.__class__)
        search_fields = []
        for ii in self.search_fields:
            if getattr(ii, "boost", None):
                search_fields.append("{0}^{1}".format(ii.field_name, ii.boost))
            else:
                search_fields.append(ii.field_name)
        query = {
            "query": {
                "filtered": {
                    "filter": {
                        "term": {
                            "live_filter": True
                        }
                    },
                    "query": {
                        "more_like_this": {
                            "docs": [{
                                "_id": mapping.get_document_id(self),
                                "_type": mapping.get_document_type()
                            }],
                            "min_doc_freq":
                            1,
                            "min_term_freq":
                            2,
                            "max_query_terms":
                            500,
                            "min_word_length":
                            4,
                            "fields":
                            search_fields
                        }
                    }
                }
            }
        }

        try:
            mlt = es_backend.es.search(index=es_backend.index_name,
                                       doc_type=mapping.get_document_type(),
                                       body=query)
        except ConnectionError:
            return []
        # Get pks from results
        pks = [hit['_source']['pk']
               for hit in mlt['hits']['hits']][:max_results]

        # Initialise results dictionary
        results = dict((str(pk), None) for pk in pks)

        # Find objects in database and add them to dict
        queryset = self._default_manager.filter(pk__in=pks)
        for obj in queryset:
            results[str(obj.pk)] = obj

        # Return results in order given by ElasticSearch
        return [results[str(pk)] for pk in pks if results[str(pk)]]