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?