Skip to content

Commit

Permalink
Add support for Solr group queries to Solr service
Browse files Browse the repository at this point in the history
This adds a new method for the Solr service, `.group_query()`, which
allows running Solr queries which group returned documents.

<https://solr.apache.org/guide/6_6/result-grouping.html>

This only implements the `group.query` option, not `group.field` or
`group.func`.
  • Loading branch information
Patrick Golden committed Nov 26, 2024
1 parent af5ab7b commit b87a51b
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 1 deletion.
21 changes: 21 additions & 0 deletions backend/src/monarch_py/datamodels/solr.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class SolrQuery(BaseModel):
facet_queries: Optional[List[str]] = Field(default_factory=list)
filter_queries: Optional[List[str]] = Field(default_factory=list)
facet_mincount: int = 1
group: bool = False
group_queries: Optional[List[str]] = Field(default_factory=list)
group_limit: int = 5
group_offset: int = 0
query_fields: Optional[str] = None
def_type: str = "edismax"
q_op: str = "AND" # See SOLR-8812, need this plus mm=100% to allow boolean operators in queries
Expand Down Expand Up @@ -88,6 +92,12 @@ def _solrize(self, value):
return "fq"
elif value == "facet_mincount":
return "facet.mincount"
elif value == "group_queries":
return "group.query"
elif value == "group_limit":
return "group.limit"
elif value == "group_offset":
return "group.offset"
elif value == "query_fields":
return "qf"
elif value == "def_type":
Expand Down Expand Up @@ -118,7 +128,18 @@ class SolrFacetCounts(BaseModel):
facet_queries: Optional[Dict]


class SolrQueryGroup(BaseModel):
matches: int
doclist: SolrQueryResponse


class SolrQueryResult(BaseModel):
responseHeader: SolrQueryResponseHeader
response: SolrQueryResponse
facet_counts: Optional[SolrFacetCounts]


class SolrGroupedQueryResult(BaseModel):
responseHeader: SolrQueryResponseHeader
grouped: Dict[str, SolrQueryGroup]
facet_counts: Optional[SolrFacetCounts]
24 changes: 23 additions & 1 deletion backend/src/monarch_py/service/solr_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import requests
from loguru import logger
from monarch_py.datamodels.solr import SolrQuery, SolrQueryResult, core
from monarch_py.datamodels.solr import SolrGroupedQueryResult, SolrQuery, SolrQueryResult, core
from monarch_py.utils.utils import escape
from pydantic import BaseModel

Expand All @@ -23,6 +23,28 @@ def get(self, id):
return None
return entity

def group_query(self, q: SolrQuery) -> SolrGroupedQueryResult:
url = f"{self.base_url}/{self.core.value}/select?{q.query_string()}"
response = requests.get(url)
logger.debug(f"SolrService.query: {url}")
data = json.loads(response.text)
if "error" in data:
logger.error("Solr error message: " + data["error"]["msg"])
response.raise_for_status()
solr_query_result = SolrGroupedQueryResult.model_validate(data, from_attributes=True)
for group in solr_query_result.grouped.values():
for doc in group.doclist.docs:
self._strip_json(

Check warning on line 37 in backend/src/monarch_py/service/solr_service.py

View check run for this annotation

Codecov / codecov/patch

backend/src/monarch_py/service/solr_service.py#L27-L37

Added lines #L27 - L37 were not covered by tests
doc,
"_version_",
"iri",
"frequency_computed_sortable_float",
"has_quotient_sortable_float",
"has_percentage_sortable_float",
)

return solr_query_result

Check warning on line 46 in backend/src/monarch_py/service/solr_service.py

View check run for this annotation

Codecov / codecov/patch

backend/src/monarch_py/service/solr_service.py#L46

Added line #L46 was not covered by tests

def query(self, q: SolrQuery) -> SolrQueryResult:
url = f"{self.base_url}/{self.core.value}/select?{q.query_string()}"
response = requests.get(url)
Expand Down
4 changes: 4 additions & 0 deletions backend/tests/fixtures/association_counts_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def association_counts_query():
"q": "*:*",
"rows": 20,
"start": 0,
"group": False,
"group_limit": 5,
"group_offset": 0,
"group_queries": [],
"facet": True,
"facet_min_count": 1,
"facet_fields": [],
Expand Down
4 changes: 4 additions & 0 deletions backend/tests/fixtures/association_query_direct.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def association_query_direct():
"q": "test:q",
"rows": 100,
"start": 100,
"group": False,
"group_limit": 5,
"group_offset": 0,
"group_queries": [],
"facet": True,
"facet_min_count": 1,
"facet_fields": [],
Expand Down
4 changes: 4 additions & 0 deletions backend/tests/fixtures/association_query_indirect.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def association_query_indirect():
"q": "test:q",
"rows": 100,
"start": 100,
"group": False,
"group_limit": 5,
"group_offset": 0,
"group_queries": [],
"facet": True,
"facet_min_count": 1,
"facet_fields": [],
Expand Down
4 changes: 4 additions & 0 deletions backend/tests/fixtures/autocomplete_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def autocomplete_query():
"q": "fanc",
"rows": 10,
"start": 0,
"group": False,
"group_limit": 5,
"group_offset": 0,
"group_queries": [],
"facet": True,
"facet_min_count": 1,
"facet_fields": [],
Expand Down
4 changes: 4 additions & 0 deletions backend/tests/fixtures/histopheno_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def histopheno_query():
"q": "*:*",
"rows": 0,
"start": 0,
"group": False,
"group_limit": 5,
"group_offset": 0,
"group_queries": [],
"facet": True,
"facet_min_count": 1,
"facet_fields": [],
Expand Down
4 changes: 4 additions & 0 deletions backend/tests/fixtures/mapping_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def mapping_query():
"q": "*:*",
"rows": 20,
"start": 0,
"group": False,
"group_limit": 5,
"group_offset": 0,
"group_queries": [],
"facet": True,
"facet_min_count": 1,
"facet_fields": [],
Expand Down
4 changes: 4 additions & 0 deletions backend/tests/fixtures/search_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def search_query():
"q": "fanconi",
"rows": 20,
"start": 0,
"group": False,
"group_limit": 5,
"group_offset": 0,
"group_queries": [],
"facet": True,
"facet_min_count": 1,
"facet_fields": [],
Expand Down

0 comments on commit b87a51b

Please sign in to comment.