@@ -321,10 +321,18 @@ We will use the following example model::
321321 def __str__(self):
322322 return self.name
323323
324- .. fieldlookup :: embeddedmodelarrayfield.overlap
324+ KeyTransform
325+ ^^^^^^^^^^^^
325326
326- ``overlap ``
327- ^^^^^^^^^^^
327+ Key transforms for :class: `EmbeddedModelArrayField ` allow querying fields of
328+ the embedded model. This is done by composing the two involved paths: the path
329+ to the ``EmbeddedModelArrayField `` and the path within the nested embedded model.
330+ This composition enables generating the appropriate query for the lookups.
331+
332+ .. fieldlookup :: embeddedmodelarrayfield.in
333+
334+ ``in ``
335+ ^^^^^^
328336
329337Returns objects where any of the embedded documents in the field match any of
330338the values passed. For example:
@@ -339,10 +347,10 @@ the values passed. For example:
339347 ... name="Third post", tags=[Tag(label="tutorial"), Tag(label="django")]
340348 ... )
341349
342- >>> Post.objects.filter(tags__label__overlap =["thoughts"])
350+ >>> Post.objects.filter(tags__label__in =["thoughts"])
343351 <QuerySet [<Post: First post>, <Post: Second post>]>
344352
345- >>> Post.objects.filter(tags__label__overlap =["tutorial", "thoughts"])
353+ >>> Post.objects.filter(tags__label__in =["tutorial", "thoughts"])
346354 <QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
347355
348356 .. fieldlookup :: embeddedmodelarrayfield.len
@@ -381,45 +389,115 @@ given value. This acts like an existence filter on matching embedded documents.
381389 >>> Post.objects.filter(tags__label__exact="tutorial")
382390 <QuerySet [<Post: Second post>]>
383391
384- Note that this does **not ** require the whole array to match, only that at
385- least one embedded document matches exactly.
392+ .. fieldlookup :: embeddedmodelarrayfield.iexact
386393
387- Keytransforms
388- ^^^^^^^^^^^^^
394+ `` iexact ``
395+ ^^^^^^^^^^
389396
390- Key transforms for :class: ` EmbeddedModelArrayField ` allow querying fields of
391- the embedded model. The transform checks if ** any ** element in the array has a
392- field matching the condition, similar to MongoDB behavior. For example:
397+ Returns objects where ** any ** embedded model in the array has a field that
398+ matches the given value ** case-insensitively **. This works like `` exact `` but
399+ ignores letter casing.
393400
394401.. code-block :: pycon
395402
403+
396404 >>> Post.objects.create(
397- ... name="First post", tags=[Tag(label="thoughts"), Tag(label="django")]
398- ... )
399- >>> Post.objects.create(name="Second post", tags=[Tag(label="thoughts")])
400- >>> Post.objects.create(
401- ... name="Third post",
402- ... tags=[Tag(label="django"), Tag(label="python"), Tag(label="thoughts")],
405+ ... name="First post", tags=[Tag(label="Thoughts"), Tag(label="Django")]
403406 ... )
407+ >>> Post.objects.create(name="Second post", tags=[Tag(label="tutorial")])
404408
405- >>> Post.objects.filter(tags__label="django")
406- <QuerySet [<Post: First post>, <Post: Third post>]>
409+ >>> Post.objects.filter(tags__label__iexact="django")
410+ <QuerySet [<Post: First post>]>
411+
412+ >>> Post.objects.filter(tags__label__iexact="TUTORIAL")
413+ <QuerySet [<Post: Second post>]>
414+
415+ .. fieldlookup :: embeddedmodelarrayfield.gt
416+ .. fieldlookup :: embeddedmodelarrayfield.gte
417+ .. fieldlookup :: embeddedmodelarrayfield.lt
418+ .. fieldlookup :: embeddedmodelarrayfield.lte
419+
420+ ``Greater Than, Greater Than or Equal, Less Than, Less Than or Equal ``
421+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
407422
408- Transforms can be chained:
423+ These lookups return objects where **any ** embedded document contains a value
424+ that satisfies the corresponding comparison. These are typically used on
425+ numeric or comparable fields within the embedded model.
426+
427+ Examples:
409428
410429.. code-block :: pycon
411430
412- >>> Post.objects.filter(tags__label__overlap=["django"])
413- <QuerySet [<Post: First post>, <Post: Third post>]>
431+ Post.objects.create(
432+ name="First post", tags=[Tag(label="django", rating=5), Tag(label="rest", rating=3)]
433+ )
434+ Post.objects.create(
435+ name="Second post", tags=[Tag(label="python", rating=2)]
436+ )
437+
438+ Post.objects.filter(tags__rating__gt=3)
439+ <QuerySet [<Post: First post>]>
440+
441+ Post.objects.filter(tags__rating__gte=3)
442+ <QuerySet [<Post: First post>, <Post: Second post>]>
443+
444+ Post.objects.filter(tags__rating__lt=3)
445+ <QuerySet []>
446+
447+ Post.objects.filter(tags__rating__lte=3)
448+ <QuerySet [<Post: First post>, <Post: Second post>]>
449+
450+ .. fieldlookup :: embeddedmodelarrayfield.all
414451
452+ ``all ``
453+ ^^^^^^^
454+
455+ Returns objects where **all ** values provided on the right-hand side are
456+ present. It requires that *every * value be matched by some document in
457+ the array.
415458
416- Indexed access is also supported :
459+ Example :
417460
418461.. code-block :: pycon
419462
420- >>> Post.objects.filter(tags__0__label="django")
463+ Post.objects.create(
464+ name="First post", tags=[Tag(label="django"), Tag(label="rest")]
465+ )
466+ Post.objects.create(
467+ name="Second post", tags=[Tag(label="django")]
468+ )
469+
470+ Post.objects.filter(tags__label__all=["django", "rest"])
421471 <QuerySet [<Post: First post>]>
422472
473+ Post.objects.filter(tags__label__all=["django"])
474+ <QuerySet [<Post: First post>, <Post: Second post>]>
475+
476+ .. fieldlookup :: embeddedmodelarrayfield.contained_by
477+
478+ ``contained_by ``
479+ ^^^^^^^^^^^^^^^^
480+
481+ Returns objects where the embedded model array is **contained by ** the list of
482+ values on the right-hand side. In other words, every value in the embedded
483+ array must be present in the given list.
484+
485+ Example:
486+
487+ .. code-block :: pycon
488+
489+ Post.objects.create(
490+ name="First post", tags=[Tag(label="django"), Tag(label="rest")]
491+ )
492+ Post.objects.create(
493+ name="Second post", tags=[Tag(label="django")]
494+ )
495+
496+ Post.objects.filter(tags__label__contained_by=["django", "rest", "api"])
497+ <QuerySet [<Post: First post>, <Post: Second post>]>
498+
499+ Post.objects.filter(tags__label__contained_by=["django"])
500+ <QuerySet [<Post: Second post>]>
423501
424502 ``ObjectIdAutoField ``
425503---------------------
0 commit comments