Skip to content

Commit bca55c7

Browse files
p-mongop
andauthored
MONGOID-4781 Refactor embedded matchers to behave as MongoDB server queries (#4783)
Co-authored-by: Oleg Pudeyev <[email protected]>
1 parent 3d1f144 commit bca55c7

File tree

3 files changed

+385
-115
lines changed

3 files changed

+385
-115
lines changed

source/tutorials/mongoid-queries.txt

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,24 +1729,26 @@ The following code illustrates retrieving the statistics:
17291729
from the raw results if multiple statistics are desired.
17301730

17311731

1732-
Full Text Search
1733-
================
1732+
.. _text-search:
17341733

1735-
To perform full text search with Mongoid, follow these steps:
1734+
Text Search
1735+
===========
17361736

1737-
1. Define a full text search index on a model.
1738-
2. Create the full text search index on the server.
1739-
3. Build a full text search query.
1737+
To perform text search with Mongoid, follow these steps:
17401738

1739+
1. Define a text index on a model.
1740+
2. Create the text index on the server.
1741+
3. Build a text search query.
17411742

1742-
Defining Full Text Search Index
1743-
-------------------------------
1743+
1744+
Defining Text Search Index
1745+
--------------------------
17441746

17451747
Index definition through Mongoid is described in detail on the `indexes
1746-
<mongoid-indexes>`_ page. Full text search indexes are described in detail on
1748+
<mongoid-indexes>`_ page. Text search indexes are described in detail
17471749
under `text indexes <https://docs.mongodb.com/manual/core/index-text/>`_
17481750
in the MongoDB manual. Below is an example definition of a Band model with
1749-
a full text search index specified on the description field:
1751+
a text index utilizing the description field:
17501752

17511753
.. code-block:: ruby
17521754

@@ -1762,8 +1764,8 @@ a full text search index specified on the description field:
17621764
Note that the index type (``text``) must be given as a string, not as a symbol.
17631765

17641766

1765-
Creating Full Text Search Index
1766-
-------------------------------
1767+
Creating Text Index
1768+
-------------------
17671769

17681770
To create the index, invoke the ``db:mongoid:create_indexes`` Rake task:
17691771

@@ -1772,8 +1774,8 @@ To create the index, invoke the ``db:mongoid:create_indexes`` Rake task:
17721774
bundle exec rake db:mongoid:create_indexes
17731775

17741776

1775-
Querying Using Full Text Search Index
1776-
-------------------------------------
1777+
Querying Using Text Index
1778+
-------------------------
17771779

17781780
To find bands whose description contains "ounces" or its variations, use the
17791781
`$text operator <https://docs.mongodb.com/manual/reference/operator/query/text/#op._S_text>`_:
@@ -1786,6 +1788,6 @@ To find bands whose description contains "ounces" or its variations, use the
17861788
Note that the description contains the word "ounce" even though the search
17871789
query was "ounces".
17881790

1789-
Note also that when performing a full text search, the name of the field is
1790-
not explicitly specified - ``$text`` operator searches all fields indexed with
1791-
full text search indexes.
1791+
Note also that when performing text search, the name of the field is not
1792+
explicitly specified - ``$text`` operator searches all fields indexed with
1793+
the text index.

source/tutorials/mongoid-relations.txt

Lines changed: 152 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,68 @@ to the other in the form of an array.
241241
"band_ids" : [ ObjectId("4d3ed089fb60ab534684b7e9") ]
242242
}
243243

244+
245+
Querying Referenced Associations
246+
--------------------------------
247+
248+
In most cases, efficient queries across referenced associations (and in general
249+
involving data or conditions or multiple collections) are performed using
250+
the aggregation pipeline. Mongoid helpers for constructing aggregation pipeline
251+
queries are described in the :ref:`aggregation pipeline <aggregation-pipeline>`
252+
section.
253+
254+
For simple queries, the use of aggregation pipeline may be avoided and
255+
associations may be queried directly. When querying associations directly,
256+
all conditions must be on that association's collection only (which typically
257+
means association in question and any associations embedded in it).
258+
259+
For example, given the following models:
260+
261+
.. code-block:: ruby
262+
263+
class Band
264+
include Mongoid::Document
265+
266+
has_many :tours
267+
has_many :awards
268+
269+
field :name, type: String
270+
end
271+
272+
class Tour
273+
include Mongoid::Document
274+
275+
belongs_to :band
276+
277+
field :year, type: Integer
278+
end
279+
280+
class Award
281+
include Mongoid::Document
282+
283+
belongs_to :band
284+
285+
field :name, type: String
286+
end
287+
288+
One could retrieve all bands that have toured since 2000 as follows:
289+
290+
.. code-block:: ruby
291+
292+
band_ids = Tour.where(year: {'$gte' => 2000}).pluck(:band_id)
293+
bands = Band.find(band_ids)
294+
295+
The conditions on ``Tour`` can be arbitrarily complex, but they must all
296+
be on the same ``Tour`` document (or documents embedded in ``Tour``).
297+
298+
To find awards for bands that have toured since 2000:
299+
300+
.. code-block:: ruby
301+
302+
band_ids = Tour.where(year: {'$gte' => 2000}).pluck(:band_id)
303+
awards = Award.where(band_id: {'$in' => band_ids})
304+
305+
244306
Embedded Associations
245307
=====================
246308

@@ -442,6 +504,92 @@ help of MongoDB projection operation:
442504
Band.where(started_on: {'$gt' => Time.now - 1.year}).only(:label).map(&:label).compact.uniq
443505

444506

507+
Querying Embedded Associations
508+
------------------------------
509+
510+
When querying top-level documents, conditions can be specified on documents
511+
in embedded associations using the dot notation. For example, given the
512+
following models:
513+
514+
.. code-block:: ruby
515+
516+
class Band
517+
include Mongoid::Document
518+
embeds_many :tours
519+
embeds_many :awards
520+
field :name, type: String
521+
end
522+
523+
class Tour
524+
include Mongoid::Document
525+
embedded_in :band
526+
field :year, type: Integer
527+
end
528+
529+
class Award
530+
include Mongoid::Document
531+
embedded_in :band
532+
field :name, type: String
533+
end
534+
535+
To retrieve bands based on tour attributes, use the dot notation as follows:
536+
537+
.. code-block:: ruby
538+
539+
# Get all bands that have toured since 2000
540+
Band.where('tours.year' => {'$gte' => 2000})
541+
542+
To retrieve only documents of embedded associations, without retrieving
543+
top-level documents, use the ``pluck`` projection method:
544+
545+
.. code-block:: ruby
546+
547+
# Get awards for bands that have toured since 2000
548+
Band.where('tours.year' => {'$gte' => 2000}).pluck(:awards)
549+
550+
.. _embedded-matching:
551+
552+
Querying Loaded Associations
553+
````````````````````````````
554+
555+
Mongoid query methods can be used on embedded associations of documents which
556+
are already loaded in the application. This mechanism is sometimes called
557+
"embedded matching" or "embedded document matching" and it is implemented
558+
entirely in Mongoid - the queries are NOT sent to the server.
559+
560+
Embedded matching is supported for most general-purpose query operators. It
561+
is not implemented for :ref:`text search <text-search>`, :manual:`geospatial query
562+
operators </reference/operator/query-geospatial/>`,
563+
operators that execute JavaScript code (:manual:`$where </reference/operator/query/where/>`)
564+
and operators that are implemented via other server functionality such as
565+
:manual:`$expr <https://docs.mongodb.com/manual/reference/operator/query/expr/>`
566+
and :manual:`$jsonSchema <https://docs.mongodb.com/manual/reference/operator/query/jsonSchema/>`.
567+
The following operators are supported:
568+
569+
- :manual:`Comparison operators </reference/operator/query-comparison/>`.
570+
- :manual:`Logical operators </reference/operator/query-logical/>`.
571+
- :manual:`$exists </reference/operator/query/exists/>`
572+
(:manual:`$type </reference/operator/query/type/>` is not currently supported).
573+
- :manual:`$regex </reference/operator/query/regex/>` (``$options`` field
574+
is not currently supported, the options must be given as part of the
575+
regular expression object).
576+
- :manual:`Array query operators </reference/operator/query-array/>`.
577+
578+
For example, using the model definitions just given, we could query
579+
tours on a loaded band:
580+
581+
.. code-block:: ruby
582+
583+
band = Band.where(name: 'Astral Projection').first
584+
tours = band.tours.where(year: {'$gte' => 2000})
585+
586+
.. note::
587+
588+
Mongoid aims to provide the same semantics when performing embedded matching
589+
as those of MongoDB server. This means, for example, that embedded matchers
590+
generally support arguments of the same types as ``Criteria`` methods do.
591+
592+
445593
Common Behavior
446594
===============
447595

@@ -996,104 +1144,10 @@ with, and is useful for developers of extensions to Mongoid.
9961144
- Returns whether the association has an associated validation.
9971145

9981146

999-
Querying Associations
1000-
=====================
1001-
1002-
Mongoid supports several forms of efficient querying of documents based on
1003-
associations.
1004-
1005-
1006-
Embedded Associations
1007-
---------------------
1008-
1009-
Given the following models:
1010-
1011-
.. code-block:: ruby
1012-
1013-
class Band
1014-
include Mongoid::Document
1015-
embeds_many :tours
1016-
embeds_many :awards
1017-
field :name, type: String
1018-
end
1019-
1020-
class Tour
1021-
include Mongoid::Document
1022-
embedded_in :band
1023-
field :year, type: Integer
1024-
end
1025-
1026-
class Award
1027-
include Mongoid::Document
1028-
embedded_in :band
1029-
field :name, type: String
1030-
end
1031-
1032-
Mongoid allows retrieving bands whose tours have certain attributes via the
1033-
dot notation, as follows:
1034-
1035-
.. code-block:: ruby
1036-
1037-
# Get all bands that have toured since 2000
1038-
Band.where('tours.year' => {'$gte' => 2000})
1039-
1040-
Mongoid also can retrieve embedded documents only, without retrieving top-level
1041-
documents, using projection:
1042-
1043-
.. code-block:: ruby
1044-
1045-
# Get awards for bands that have toured since 2000
1046-
Band.where('tours.year' => {'$gte' => 2000}).pluck(:awards)
1047-
1048-
1049-
Referenced Associations
1050-
-----------------------
1051-
1052-
If the associations are referenced rather than embedded, performing queries
1053-
through them takes a bit more work. Given the following models modified from
1054-
the previous example:
1055-
1056-
.. code-block:: ruby
1057-
1058-
class Band
1059-
include Mongoid::Document
1060-
has_many :tours
1061-
has_many :awards
1062-
field :name, type: String
1063-
end
1064-
1065-
class Tour
1066-
include Mongoid::Document
1067-
belongs_to :band
1068-
field :year, type: Integer
1069-
end
1070-
1071-
class Award
1072-
include Mongoid::Document
1073-
belongs_to :band
1074-
field :name, type: String
1075-
end
1076-
1077-
One could retrieve all bands that have toured since 2000 as follows:
1078-
1079-
.. code-block:: ruby
1080-
1081-
band_ids = Tour.where(year: {'$gte' => 2000}).pluck(:band_id)
1082-
bands = Band.find(band_ids)
1083-
1084-
The conditions on ``Tour`` can be arbitrarily complex, but they must all
1085-
be on the same ``Tour`` document (or documents embedded in ``Tour``).
1086-
1087-
To find awards for bands that have toured since 2000:
1088-
1089-
.. code-block:: ruby
1090-
1091-
band_ids = Tour.where(year: {'$gte' => 2000}).pluck(:band_id)
1092-
awards = Award.where(band_id: {'$in' => band_ids})
1093-
1147+
.. _aggregation-pipeline:
10941148

10951149
Aggregation Pipeline
1096-
--------------------
1150+
====================
10971151

10981152
Mongoid exposes MongoDB's aggregation pipeline for queries involving multiple
10991153
referenced associations at the same time. Given the same setup as before with
@@ -1156,8 +1210,8 @@ having to send the list of document ids to Mongoid in the second query
11561210

11571211
.. _aggregation-pipeline-builder-dsl:
11581212

1159-
Aggregation Pipeline Builder DSL
1160-
--------------------------------
1213+
Builder DSL
1214+
-----------
11611215

11621216
Mongoid provides limited support for constructing the aggregation pipeline
11631217
itself using a high-level DSL. The following aggregation pipeline operators

0 commit comments

Comments
 (0)