@@ -299,6 +299,207 @@ These indexes use 0-based indexing.
299
299
As described above for :class: `EmbeddedModelField `,
300
300
:djadmin: `makemigrations ` does not yet detect changes to embedded models.
301
301
302
+ Querying ``EmbeddedModelArrayField ``
303
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
304
+
305
+ There are a number of custom lookups and a transform for
306
+ :class: `EmbeddedModelArrayField `, similar to those available
307
+ for :class: `ArrayField `.
308
+ We will use the following example model::
309
+
310
+ from django.db import models
311
+ from django_mongodb_backend.fields import EmbeddedModelArrayField
312
+
313
+
314
+ class Tag(EmbeddedModel):
315
+ label = models.CharField(max_length=100)
316
+
317
+ class Post(models.Model):
318
+ name = models.CharField(max_length=200)
319
+ tags = EmbeddedModelArrayField(Tag)
320
+
321
+ def __str__(self):
322
+ return self.name
323
+
324
+ Embedded field lookup
325
+ ^^^^^^^^^^^^^^^^^^^^^
326
+
327
+ Embedded field lookup for :class: `EmbeddedModelArrayField ` allow querying
328
+ fields of the embedded model. This is done by composing the two involved paths:
329
+ the path to the ``EmbeddedModelArrayField `` and the path within the nested
330
+ embedded model.
331
+ This composition enables generating the appropriate query for the lookups.
332
+
333
+ .. fieldlookup :: embeddedmodelarrayfield.in
334
+
335
+ ``in ``
336
+ ^^^^^^
337
+
338
+ Returns objects where any of the embedded documents in the field match any of
339
+ the values passed. For example:
340
+
341
+ .. code-block :: pycon
342
+
343
+ >>> Post.objects.create(
344
+ ... name="First post", tags=[Tag(label="thoughts"), Tag(label="django")]
345
+ ... )
346
+ >>> Post.objects.create(name="Second post", tags=[Tag(label="thoughts")])
347
+ >>> Post.objects.create(
348
+ ... name="Third post", tags=[Tag(label="tutorial"), Tag(label="django")]
349
+ ... )
350
+
351
+ >>> Post.objects.filter(tags__label__in=["thoughts"])
352
+ <QuerySet [<Post: First post>, <Post: Second post>]>
353
+
354
+ >>> Post.objects.filter(tags__label__in=["tutorial", "thoughts"])
355
+ <QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
356
+
357
+ .. fieldlookup :: embeddedmodelarrayfield.len
358
+
359
+ ``len ``
360
+ ^^^^^^^
361
+
362
+ Returns the length of the embedded model array. The lookups available afterward
363
+ are those available for :class: `~django.db.models.IntegerField `. For example:
364
+
365
+ .. code-block :: pycon
366
+
367
+ >>> Post.objects.create(
368
+ ... name="First post", tags=[Tag(label="thoughts"), Tag(label="django")]
369
+ ... )
370
+ >>> Post.objects.create(name="Second post", tags=[Tag(label="thoughts")])
371
+
372
+ >>> Post.objects.filter(tags__len=1)
373
+ <QuerySet [<Post: Second post>]>
374
+
375
+ .. fieldlookup :: embeddedmodelarrayfield.exact
376
+
377
+ ``exact ``
378
+ ^^^^^^^^^
379
+
380
+ Returns objects where **any ** embedded model in the array exactly matches the
381
+ given value. This acts like an existence filter on matching embedded documents.
382
+
383
+ .. code-block :: pycon
384
+
385
+ >>> Post.objects.create(
386
+ ... name="First post", tags=[Tag(label="thoughts"), Tag(label="django")]
387
+ ... )
388
+ >>> Post.objects.create(name="Second post", tags=[Tag(label="tutorial")])
389
+
390
+ >>> Post.objects.filter(tags__label__exact="tutorial")
391
+ <QuerySet [<Post: Second post>]>
392
+
393
+ .. fieldlookup :: embeddedmodelarrayfield.iexact
394
+
395
+ ``iexact ``
396
+ ^^^^^^^^^^
397
+
398
+ Returns objects where **any ** embedded model in the array has a field that
399
+ matches the given value **case-insensitively **. This works like ``exact `` but
400
+ ignores letter casing.
401
+
402
+ .. code-block :: pycon
403
+
404
+
405
+ >>> Post.objects.create(
406
+ ... name="First post", tags=[Tag(label="Thoughts"), Tag(label="Django")]
407
+ ... )
408
+ >>> Post.objects.create(name="Second post", tags=[Tag(label="tutorial")])
409
+
410
+ >>> Post.objects.filter(tags__label__iexact="django")
411
+ <QuerySet [<Post: First post>]>
412
+
413
+ >>> Post.objects.filter(tags__label__iexact="TUTORIAL")
414
+ <QuerySet [<Post: Second post>]>
415
+
416
+ .. fieldlookup :: embeddedmodelarrayfield.gt
417
+ .. fieldlookup :: embeddedmodelarrayfield.gte
418
+ .. fieldlookup :: embeddedmodelarrayfield.lt
419
+ .. fieldlookup :: embeddedmodelarrayfield.lte
420
+
421
+ ``Greater Than, Greater Than or Equal, Less Than, Less Than or Equal ``
422
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
423
+
424
+ These lookups return objects where **any ** embedded document contains a value
425
+ that satisfies the corresponding comparison. These are typically used on
426
+ numeric or comparable fields within the embedded model.
427
+
428
+ Examples:
429
+
430
+ .. code-block :: pycon
431
+
432
+ Post.objects.create(
433
+ name="First post", tags=[Tag(label="django", rating=5), Tag(label="rest", rating=3)]
434
+ )
435
+ Post.objects.create(
436
+ name="Second post", tags=[Tag(label="python", rating=2)]
437
+ )
438
+
439
+ Post.objects.filter(tags__rating__gt=3)
440
+ <QuerySet [<Post: First post>]>
441
+
442
+ Post.objects.filter(tags__rating__gte=3)
443
+ <QuerySet [<Post: First post>, <Post: Second post>]>
444
+
445
+ Post.objects.filter(tags__rating__lt=3)
446
+ <QuerySet []>
447
+
448
+ Post.objects.filter(tags__rating__lte=3)
449
+ <QuerySet [<Post: First post>, <Post: Second post>]>
450
+
451
+ .. fieldlookup :: embeddedmodelarrayfield.all
452
+
453
+ ``all ``
454
+ ^^^^^^^
455
+
456
+ Returns objects where **all ** values provided on the right-hand side are
457
+ present. It requires that *every * value be matched by some document in
458
+ the array.
459
+
460
+ Example:
461
+
462
+ .. code-block :: pycon
463
+
464
+ Post.objects.create(
465
+ name="First post", tags=[Tag(label="django"), Tag(label="rest")]
466
+ )
467
+ Post.objects.create(
468
+ name="Second post", tags=[Tag(label="django")]
469
+ )
470
+
471
+ Post.objects.filter(tags__label__all=["django", "rest"])
472
+ <QuerySet [<Post: First post>]>
473
+
474
+ Post.objects.filter(tags__label__all=["django"])
475
+ <QuerySet [<Post: First post>, <Post: Second post>]>
476
+
477
+ .. fieldlookup :: embeddedmodelarrayfield.contained_by
478
+
479
+ ``contained_by ``
480
+ ^^^^^^^^^^^^^^^^
481
+
482
+ Returns objects where the embedded model array is **contained by ** the list of
483
+ values on the right-hand side. In other words, every value in the embedded
484
+ array must be present in the given list.
485
+
486
+ Example:
487
+
488
+ .. code-block :: pycon
489
+
490
+ Post.objects.create(
491
+ name="First post", tags=[Tag(label="django"), Tag(label="rest")]
492
+ )
493
+ Post.objects.create(
494
+ name="Second post", tags=[Tag(label="django")]
495
+ )
496
+
497
+ Post.objects.filter(tags__label__contained_by=["django", "rest", "api"])
498
+ <QuerySet [<Post: First post>, <Post: Second post>]>
499
+
500
+ Post.objects.filter(tags__label__contained_by=["django"])
501
+ <QuerySet [<Post: Second post>]>
502
+
302
503
``ObjectIdAutoField ``
303
504
---------------------
304
505
0 commit comments