Search: allow to search on different versions of subprojects
@@ -11,6 +11,7 @@ from elasticsearch_dsl.query import (
MultiMatch,
Nested,
SimpleQueryString,
+ Term,
Wildcard,
)
@@ -35,12 +36,23 @@ class RTDFacetedSearch(FacetedSearch):
'post_tags': ['</span>'],
}
- def __init__(self, query=None, filters=None, user=None, use_advanced_query=True, **kwargs):
+ def __init__(
+ self,
+ query=None,
+ filters=None,
+ projects=None,
+ user=None,
+ use_advanced_query=True,
+ **kwargs,
+ ):
"""
Pass in a user in order to filter search results by privacy.
- If `use_advanced_query` is `True`,
- force to always use `SimpleQueryString` for the text query object.
+ :param projects: A dictionary of project slugs mapped to a `VersionData` object.
+ Results are filter with these values.
+
+ :param use_advanced_query: If `True` forces to always use
+ `SimpleQueryString` for the text query object.
.. warning::
@@ -50,6 +62,7 @@ class RTDFacetedSearch(FacetedSearch):
self.user = user
self.filter_by_user = kwargs.pop('filter_by_user', True)
self.use_advanced_query = use_advanced_query
+ self.projects = projects or {}
# Hack a fix to our broken connection pooling
# This creates a new connection on every request,
@@ -259,7 +272,12 @@ class PageSearchBase(RTDFacetedSearch):
return s.hits.total
def query(self, search, query):
- """Manipulates the query to support nested queries and a custom rank for pages."""
+ """
+ Manipulates the query to support nested queries and a custom rank for pages.
+
+ If `self.projects` was given, we use it to filter the documents that
+ match the same project and version.
+ """
search = search.highlight_options(**self._highlight_options)
queries = self._get_queries(
@@ -280,8 +298,22 @@ class PageSearchBase(RTDFacetedSearch):
)
queries.extend([sections_nested_query, domains_nested_query])
+ bool_query = Bool(should=queries)
+
+ if self.projects:
+ versions_query = [
+ Bool(
+ must=[
+ Term(project={'value': project}),
+ Term(version={'value': version}),
+ ]
+ )
+ for project, version in self.projects.items()
+ ]
+ bool_query = Bool(must=[bool_query, Bool(should=versions_query)])
+
final_query = FunctionScore(
- query=Bool(should=queries),
+ query=bool_query,
script_score=self._get_script_score(),
)
search = search.query(final_query)
