ARTICLE AD BOX
So here's the issue. I am maintaining a somewhat large Django app and am tasked with creating a search bar that relies on elastic search data and need to in the near future convert a large number of Django DB queries into Elastic queries. I'm using python's elasticsearch.dsl package version 8.19.2 for this. Assuming the app uses Articles as a model that needs to be represented as Elastic document. Here is my implementation of the builder pattern
from elasticsearch.dsl import Document, Text, Keyword class ArticleDocument(Document): id = Integer() title = Text( fields={ 'keyword': Keyword() } ) class Index: name = INDEX_VAR from app import handle_elastic_connection @dataclass class ElasticSearchResults: count: int results: object class ArticleRepository: def __init__(self, client: Elasticsearch): self.client = client def return_results(self, search: Search): return ElasticSearchResults(results=search.execute(), count=search.count()) class ArticleQueryBuilder: def __init__( self ): # handles index refer self.search: Search = ArticleDocument.search() def builder_method1(self, list_of_values:List): if list_of_values: self.search = self.search(Q('terms', key=list_of_values)) def builder_method2(self, single_value:str): if single_value: method2_filter = Q('term', value1=single_value) | Q('term', value2=single_value) self.search = self.search(method2_filter) # .... more builder methods def build(): return self.search # Usage, most likely in view ec = handle_elastic_connection() repo = ArticleRepository(ec) artcile_search = ArticleQueryBuilder.builder_method1().builder_method2.build() results: ElasticSearchResults = repo.return_results(artcile_search)I know the builder pattern gets a lot of hate in some corners of the internet but I'm not using this as a replacement for named parameters lol. It's to make query construction easier and more similar to Django's ORM langage. I did consider alternatives
Using elasticsearch.dsl Q object directly. I could just do this directly in the view, constructing the Search object with queries right there and just calling Search.execute() in the view itself but there are a lot of operations that are going to be reused over and over by different views tied to a single model. I know a simplified the example but one thing I'm doing is filtering results based on user permissions which I'm going to be doing a lot in multiple views I feel like it's enough to justify tucking it behind at least one layer of abstraction
Using the repository pattern was what everyone did at my previous job, but the problem with that is people would make a method that was only applicable to one use and returned one set of results from the database, and then there would be a ton of extraneous methods. The builder pattern gives you the flexibility to chain them together on a single query, which I will need to do
Are there alternatives I should consider? There's not a lot of examples or documentation I can find of elastic being used in Django project, and while I'm the sole maintainer of this repo at the moment. It will most likely be maintained by a more people in the future, so I'm being a little bit over-analytical at this stage of development.
