@@ -317,10 +317,18 @@ We will use the following example model::
317317 def __str__(self):
318318 return self.name
319319
320- .. fieldlookup :: embeddedmodelarrayfield.overlap
320+ KeyTransform
321+ ^^^^^^^^^^^^
321322
322- ``overlap ``
323- ^^^^^^^^^^^
323+ Key transforms for :class: `EmbeddedModelArrayField ` allow querying fields of
324+ the embedded model. This is done by composing the two involved paths: the path
325+ to the ``EmbeddedModelArrayField `` and the path within the nested embedded model.
326+ This composition enables generating the appropriate query for the lookups.
327+
328+ .. fieldlookup :: embeddedmodelarrayfield.in
329+
330+ ``in ``
331+ ^^^^^^
324332
325333Returns objects where any of the embedded documents in the field match any of
326334the values passed. For example:
@@ -335,10 +343,10 @@ the values passed. For example:
335343 ... name="Third post", tags=[Tag(label="tutorial"), Tag(label="django")]
336344 ... )
337345
338- >>> Post.objects.filter(tags__label__overlap =["thoughts"])
346+ >>> Post.objects.filter(tags__label__in =["thoughts"])
339347 <QuerySet [<Post: First post>, <Post: Second post>]>
340348
341- >>> Post.objects.filter(tags__label__overlap =["tutorial", "thoughts"])
349+ >>> Post.objects.filter(tags__label__in =["tutorial", "thoughts"])
342350 <QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
343351
344352 .. fieldlookup :: embeddedmodelarrayfield.len
@@ -377,45 +385,115 @@ given value. This acts like an existence filter on matching embedded documents.
377385 >>> Post.objects.filter(tags__label__exact="tutorial")
378386 <QuerySet [<Post: Second post>]>
379387
380- Note that this does **not ** require the whole array to match, only that at
381- least one embedded document matches exactly.
388+ .. fieldlookup :: embeddedmodelarrayfield.iexact
382389
383- Keytransforms
384- ^^^^^^^^^^^^^
390+ `` iexact ``
391+ ^^^^^^^^^^
385392
386- Key transforms for :class: ` EmbeddedModelArrayField ` allow querying fields of
387- the embedded model. The transform checks if ** any ** element in the array has a
388- field matching the condition, similar to MongoDB behavior. For example:
393+ Returns objects where ** any ** embedded model in the array has a field that
394+ matches the given value ** case-insensitively **. This works like `` exact `` but
395+ ignores letter casing.
389396
390397.. code-block :: pycon
391398
399+
392400 >>> Post.objects.create(
393- ... name="First post", tags=[Tag(label="thoughts"), Tag(label="django")]
394- ... )
395- >>> Post.objects.create(name="Second post", tags=[Tag(label="thoughts")])
396- >>> Post.objects.create(
397- ... name="Third post",
398- ... tags=[Tag(label="django"), Tag(label="python"), Tag(label="thoughts")],
401+ ... name="First post", tags=[Tag(label="Thoughts"), Tag(label="Django")]
399402 ... )
403+ >>> Post.objects.create(name="Second post", tags=[Tag(label="tutorial")])
400404
401- >>> Post.objects.filter(tags__label="django")
402- <QuerySet [<Post: First post>, <Post: Third post>]>
405+ >>> Post.objects.filter(tags__label__iexact="django")
406+ <QuerySet [<Post: First post>]>
407+
408+ >>> Post.objects.filter(tags__label__iexact="TUTORIAL")
409+ <QuerySet [<Post: Second post>]>
410+
411+ .. fieldlookup :: embeddedmodelarrayfield.gt
412+ .. fieldlookup :: embeddedmodelarrayfield.gte
413+ .. fieldlookup :: embeddedmodelarrayfield.lt
414+ .. fieldlookup :: embeddedmodelarrayfield.lte
415+
416+ ``Greater Than, Greater Than or Equal, Less Than, Less Than or Equal ``
417+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
403418
404- Transforms can be chained:
419+ These lookups return objects where **any ** embedded document contains a value
420+ that satisfies the corresponding comparison. These are typically used on
421+ numeric or comparable fields within the embedded model.
422+
423+ Examples:
405424
406425.. code-block :: pycon
407426
408- >>> Post.objects.filter(tags__label__overlap=["django"])
409- <QuerySet [<Post: First post>, <Post: Third post>]>
427+ Post.objects.create(
428+ name="First post", tags=[Tag(label="django", rating=5), Tag(label="rest", rating=3)]
429+ )
430+ Post.objects.create(
431+ name="Second post", tags=[Tag(label="python", rating=2)]
432+ )
433+
434+ Post.objects.filter(tags__rating__gt=3)
435+ <QuerySet [<Post: First post>]>
436+
437+ Post.objects.filter(tags__rating__gte=3)
438+ <QuerySet [<Post: First post>, <Post: Second post>]>
439+
440+ Post.objects.filter(tags__rating__lt=3)
441+ <QuerySet []>
442+
443+ Post.objects.filter(tags__rating__lte=3)
444+ <QuerySet [<Post: First post>, <Post: Second post>]>
445+
446+ .. fieldlookup :: embeddedmodelarrayfield.all
410447
448+ ``all ``
449+ ^^^^^^^
450+
451+ Returns objects where **all ** values provided on the right-hand side are
452+ present. It requires that *every * value be matched by some document in
453+ the array.
411454
412- Indexed access is also supported :
455+ Example :
413456
414457.. code-block :: pycon
415458
416- >>> Post.objects.filter(tags__0__label="django")
459+ Post.objects.create(
460+ name="First post", tags=[Tag(label="django"), Tag(label="rest")]
461+ )
462+ Post.objects.create(
463+ name="Second post", tags=[Tag(label="django")]
464+ )
465+
466+ Post.objects.filter(tags__label__all=["django", "rest"])
417467 <QuerySet [<Post: First post>]>
418468
469+ Post.objects.filter(tags__label__all=["django"])
470+ <QuerySet [<Post: First post>, <Post: Second post>]>
471+
472+ .. fieldlookup :: embeddedmodelarrayfield.contained_by
473+
474+ ``contained_by ``
475+ ^^^^^^^^^^^^^^^^
476+
477+ Returns objects where the embedded model array is **contained by ** the list of
478+ values on the right-hand side. In other words, every value in the embedded
479+ array must be present in the given list.
480+
481+ Example:
482+
483+ .. code-block :: pycon
484+
485+ Post.objects.create(
486+ name="First post", tags=[Tag(label="django"), Tag(label="rest")]
487+ )
488+ Post.objects.create(
489+ name="Second post", tags=[Tag(label="django")]
490+ )
491+
492+ Post.objects.filter(tags__label__contained_by=["django", "rest", "api"])
493+ <QuerySet [<Post: First post>, <Post: Second post>]>
494+
495+ Post.objects.filter(tags__label__contained_by=["django"])
496+ <QuerySet [<Post: Second post>]>
419497
420498 ``ObjectIdAutoField ``
421499---------------------
0 commit comments