Indexing multiply nested models with django_elasticsearch_dsl

I'm trying to use Elasticsearch in my Django app. I have Lemma models that can have multiple Forms with one citation form that can, in turn, have multiple Spellings. I'm trying to execute a search on (1) the Lemma's citation form, (2) any Lemma's Form's citation form, or (3) any Lemma's Form's Spelling's Latin character spelling.

The structure in my models.py:

class Lemma(models.Model):
    cf = models.CharField(max_length=200)
    pos = models.ForeignKey(Pos, blank=True, null=True, on_delete=models.SET_NULL)
    notes = models.TextField(blank=True)
    sortform = models.CharField(max_length=200)

class LemmaDef(models.Model):
    lemma = models.ForeignKey(Lemma, on_delete=models.CASCADE, related_name="definitions")
    definition = models.TextField()

class Form(models.Model):
    lemma = models.ForeignKey(Lemma, on_delete=models.CASCADE, related_name="forms")
    cf = models.CharField(max_length=200, blank=True)
    formtype = models.ManyToManyField(FormType, blank=True)

class Spelling(models.Model):
    form = models.ForeignKey(Form, on_delete=models.CASCADE, related_name="spellings")
    spelling_lat = models.CharField(max_length=200)
    spelling_cun = models.CharField(max_length=200, blank=True)
    note = models.CharField(max_length=200, blank=True)

In documents.py, I've got:

from django_elasticsearch_dsl import Document, fields
from django_elasticsearch_dsl.registries import registry

from .models import Lemma, Pos, LemmaDef, Form, Spelling

@registry.register_document
class LemmaDocument(Document):
    pos = fields.ObjectField(properties={
        "term": fields.TextField()
    })
    definitions = fields.ObjectField(properties={
        "definition": fields.TextField()
    }) 
    forms = fields.ObjectField(properties={
        "cf": fields.TextField(),
        "spellings": fields.ObjectField(properties={
            "spelling_lat": fields.TextField()
        })
    })

    class Index:
        name = "lemma"
        settings = {
            "number_of_shards": 1,
            "number_of_replicas": 0
        }
    
    class Django:
        model = Lemma

        fields = [
            "id",
            "cf",
            "sortform",
            "notes",
        ]
        related_models = [Pos, LemmaDef, Form, Spelling]

    def get_instances_from_related(self, related_instance):
        if isinstance(related_instance, Pos):
            related_instance.lemma_set.all()
        elif isinstance(related_instance, LemmaDef):
            related_instance.lemma
        elif isinstance(related_instance, Form):
            related_instance.lemma
        elif isinstance(related_instance, Spelling):
            related_instance.form.lemma

When I run my searches, searches on definitions.definition returns the expected results, but searches on fields in forms.cf or forms.spellings.spelling_lat don't return anything.

The view is executing:

class LemmaSearchView(LemmaListView):
    template_name = "emedict/lemma_search.html"

    def get(self, request, *args, **kwargs):
        form = LemmaAdvancedSearchForm(self.request.GET or None)
        if form.is_valid():
            term = request.GET["search_term"]
            match request.GET["search_type"]:
                case "lemma":
                    fields = [
                        "cf", "forms.cf", "forms.spellings.spelling_lat", "sortform"
                    ]
                case "definition":
                    fields = ["definitions.definition"]
                case _:
                    fields = [
                        "cf", "forms.cf", "forms.spellings.spelling_lat", "sortform"
                    ]
            # TODO: convert sub nums to regular?
            q = edsl.Q(
                "multi_match",
                query = term,
                fields = fields,
                fuzziness = "auto"
            )
            search = LemmaDocument.search().query(q)
            qs: QuerySet = search.to_queryset()
            self.lemmalist = qs.distinct().order_by("sortform")
    
        return self.render_to_response(self.get_context_data(form=form))

Is there something I'm not understanding with searches that go down two nested levels?

Вернуться на верх