2

I don't understand how to search with a NestedField. I first want to filter the results using a PK and then make a search on several fields from one or more words. I created a nestedfield because the relationship is "manytomany".

My Model:

class Club(models.Model):
    """
    Sport club Model, related to :model:`auth.User` and :model:`clubs.CategoryClub`
    """
    name = models.CharField(max_length=50, verbose_name="nom")
    category = models.ForeignKey('CategoryClub', on_delete=models.CASCADE)
    clubs_members = models.ManyToManyField(User, related_name="clubs_members", blank=True)
    token = models.CharField(max_length=8, unique=True, blank=True, null=True)

    class Meta:
        verbose_name = "Club"
        verbose_name_plural = "Clubs"

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("detailClub", kwargs={"pk": self.pk})

My document:

@registry.register_document
class UserDocument(Document):
    clubs_members = fields.NestedField(properties={
        'pk': fields.IntegerField(),
        'name': fields.TextField(),
    })
class Index:
        # Name of the Elasticsearch index
        name = 'user'
        # See Elasticsearch Indices API reference for available settings
        settings = {'number_of_shards': 1,
                    'number_of_replicas': 0}

    class Django:
        model = User # The model associated with this Document

        # The fields of the model you want to be indexed in Elasticsearch

        fields = [
            'id',
            'first_name',
            'last_name',
            'email',
        ]

My view:

            search = UserDocument.search()
            search = search.query(
                'nested',
                path='clubs_members',
                query=Q('match', clubs_members__pk=request.user.profil.club_administrator.pk)
                # request.user.profil.club_administrator.pk == 1 in my example
            )

            if form.cleaned_data['search'] != "":
                search = search.query(
                    Qelastic('bool',
                    should=[
                        Qelastic('multi_match',
                        query=form.cleaned_data['search'],
                        fields=['last_name^2', 'first_name^2', 'email^1'],
                        fuzziness="auto"
                        ),
                    ],
                    minimum_should_match=1
                    )
                )

            
            response = search[start:end].execute()

An example of document in ES:

{
  "_index": "user",
  "_type": "_doc",
  "_id": "1",
  "_version": 1,
  "_seq_no": 0,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "profil": {
      "phone": "010101011",
      "address": "city center",
      "city": "New York",
      "postalCode": "555",
      "avatar": "/media/avatars/2.jpg"
    },
    "clubs_members": [
      {
        "pk": 1,
        "name": "Tennis club"
      },
      {
        "pk": 2,
        "name": "Football club"
      }
    ],
    "id": 1,
    "first_name": "Django",
    "last_name": "Fett",
    "email": "django@fett.com"
  }
}

Traceback:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/dashboard/recherche/

Django Version: 2.2.16
Python Version: 3.8.6
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admindocs',
 'django_elasticsearch_dsl',
 'django_elasticsearch_dsl_drf',
 'easy_thumbnails',
 'bootstrap4',
 'bootstrap_datepicker_plus',
 'debug_toolbar',
 'paypal.standard.ipn',
 'customfilters',
 'utilisateurs',
 'clubs',
 'dashboard',
 'teams',
 'blog',
 'competition',
 'ideasbox',
 'paiement']
Installed Middleware:
['debug_toolbar.middleware.DebugToolbarMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/home/aurelien/.local/lib/python3.8/site-packages/elasticsearch_dsl/utils.py" in get_dsl_class
  219.             return cls._classes[name]

During handling of the above exception (<Q: (AND: match, ('clubs_members__pk', 1))>), another exception occurred:

File "/home/aurelien/.local/lib/python3.8/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/home/aurelien/.local/lib/python3.8/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/home/aurelien/.local/lib/python3.8/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/aurelien/dev/gsport/dashboard/views.py" in search
  1154.             search = search.query(

File "/home/aurelien/.local/lib/python3.8/site-packages/elasticsearch_dsl/search.py" in __call__
  43.             proxied._proxied = Q(*args, **kwargs)

File "/home/aurelien/.local/lib/python3.8/site-packages/elasticsearch_dsl/query.py" in Q
  34.     return Query.get_dsl_class(name_or_query)(**params)

File "/home/aurelien/.local/lib/python3.8/site-packages/elasticsearch_dsl/utils.py" in __init__
  230.             self._setattr(pname, pvalue)

File "/home/aurelien/.local/lib/python3.8/site-packages/elasticsearch_dsl/utils.py" in _setattr
  283.                     value = shortcut(value)

File "/home/aurelien/.local/lib/python3.8/site-packages/elasticsearch_dsl/query.py" in Q
  34.     return Query.get_dsl_class(name_or_query)(**params)

File "/home/aurelien/.local/lib/python3.8/site-packages/elasticsearch_dsl/utils.py" in get_dsl_class
  223.             raise UnknownDslObject('DSL class `{}` does not exist in {}.'.format(name, cls._type_name))

Exception Type: UnknownDslObject at /dashboard/recherche/
Exception Value: DSL class `(AND: match, ('clubs_members__pk', 1))` does not exist in query.

How can I filter the results by choosing "clubs_members" with a pk?

darkvodka
  • 303
  • 1
  • 3
  • 11

1 Answers1

0

Possibly because the Q you are using is imported from

from django.db.models import Q

Instead this try to import it from elasticsearch_dsl like this

from elasticsearch_dsl.query import Q