From c453ea2cb07cbcb2ee5175693563bb00632cc778 Mon Sep 17 00:00:00 2001 From: rustagir Date: Tue, 29 Oct 2024 10:36:30 -0400 Subject: [PATCH 1/6] DOCSP-42753: specify query part 1 --- snooty.toml | 3 +- source/includes/interact-data/query.rb | 161 +++++++++ source/interact-data.txt | 12 +- source/interact-data/specify-query.txt | 476 +++++++++++++++++++++++++ 4 files changed, 645 insertions(+), 7 deletions(-) create mode 100644 source/includes/interact-data/query.rb create mode 100644 source/interact-data/specify-query.txt diff --git a/snooty.toml b/snooty.toml index 17839cec..5ae4acc9 100644 --- a/snooty.toml +++ b/snooty.toml @@ -7,7 +7,8 @@ intersphinx = [ "https://www.mongodb.com/docs/manual/objects.inv", toc_landing_pages = [ "/quick-start-rails", - "/quick-start-sinatra" + "/quick-start-sinatra", + "/interact-data" ] [constants] diff --git a/source/includes/interact-data/query.rb b/source/includes/interact-data/query.rb new file mode 100644 index 00000000..2e6046fb --- /dev/null +++ b/source/includes/interact-data/query.rb @@ -0,0 +1,161 @@ +# start-simple-field-query +Band.where(name: 'Depeche Mode') +Band.where(name => 'Depeche Mode') +# end-simple-field-query + +# start-query-api-query +Band.where(founded: {'$gt' => 1980}) +Band.where('founded' => {'$gt' => 1980}) +# end-query-api-query + +# start-symbol-query +Band.where(:founded.gt => 1980) +# end-symbol-query + +# start-defined-field-query +Band.where(founded: '2020') +# end-defined-field-query + +# start-raw-field-query +Band.where(founded: Mongoid::RawValue('2020')) +# end-raw-field-query + +# start-id-field-query +Band.where(id: '5ebdeddfe1b83265a376a760') +# end-id-field-query + +# start-embedded-query +Band.where('manager.name' => 'Smith') +# end-embedded-query + +# start-embedded-ne-query +Band.where(:'manager.name'.ne => 'Smith') +# end-embedded-ne-query + +# start-logical-ops +# Uses "and" to combine criteria +Band.where(label: 'Trust in Trance').and(name: 'Astral Projection') + +# Uses "or" to specify criteria +Band.where(label: 'Trust in Trance').or(Band.where(name: 'Astral Projection')) + +# Uses "not" to specify criteria +Band.not(label: 'Trust in Trance', name: 'Astral Projection') + +# Uses "not" without arguments +Band.not.where(label: 'Trust in Trance', name: 'Astral Projection') +# end-logical-ops + +# start-logical-and-ops +# Conditions passed to separate "and" calls +Band.and(name: 'Sun Kil Moon').and(member_count: 2) + +# Multiple conditions in the same "and" call +Band.and({name: 'Sun Kil Moon'}, {member_count: 2}) + +# Multiple conditions in an array - Deprecates +Band.and([{name: 'Sun Kil Moon'}, {member_count: 2}]) + +# Condition in "where" and a scope +Band.where(name: 'Sun Kil Moon').and(Band.where(member_count: 2)) + +# Condition in "and" and a scope +Band.and({name: 'Sun Kil Moon'}, Band.where(member_count: 2)) + +# Scope as an array element, nested arrays - Deprecated +Band.and([Band.where(name: 'Sun Kil Moon'), [{member_count: 2}]]) +# end-logical-and-ops + +# start-logical-combination-ops +# Combines as "and" +Band.where(name: 'Swans').where(name: 'Feist').selector + +# Combines as "or" +Band.where(name: 'Swans').or(name: 'Feist').selector +# end-logical-combination-ops + +# start-logical-combination-ops-2 +# "or" applies to the first condition, and the second is combined +# as "and" +Band.or(name: 'Sun').where(label: 'Trust').selector + +# Same as previous example - where and and are aliases +Band.or(name: 'Sun').and(label: 'Trust').selector + +# Same operator can be stacked any number of times +Band.or(name: 'Sun').or(label: 'Trust').selector + +# The last label condition is added to the top level as "and" +Band.where(name: 'Sun').or(label: 'Trust').where(label: 'Feist').selector +# => {"$or"=>[{"name"=>"Sun"}, {"label"=>"Trust"}], "label"=>"Foo"} +# end-logical-combination-ops-2 + +# start-not-logical +# "not" negates "where" +Band.not.where(name: 'Best').selector + +# The second "where" is added as "$and" +Band.not.where(name: 'Best').where(label: /Records/).selector + +# "not" negates its argument +Band.not(name: 'Best').selector +# end-not-logical + +# start-not-logical-note +# String negation - uses "$ne" +Band.not.where(name: 'Best').selector + +# Regex negation - uses "$not" +Band.not.where(name: /Best/).selector +# end-not-logical-note + +# start-not-behavior +# Simple condition +Band.not(name: /Best/).selector + +# Complex conditions +Band.where(name: /Best/).not(name: 'Astral Projection').selector + +# Symbol operator syntax +Band.not(:name.ne => 'Astral Projection') +# end-not-behavior + +# start-incremental-1 +Band.in(name: ['a']).in(name: ['b']) +# Interpreted query: +# {"name"=>{"$in"=>["a"]}, "$and"=>[{"name"=>{"$in"=>["b"]}}]} +# end-incremental-1 + +# start-in-merge +Band.in(name: ['a']).override.in(name: ['b']) +# Interpreted query: +# {"name"=>{"$in"=>["b"]}} + +Band.in(name: ['a', 'b']).intersect.in(name: ['b', 'c']) +# Interpreted query: +# {"name"=>{"$in"=>["b"]}} + +Band.in(name: ['a']).union.in(name: ['b']) +# Interpreted query: +# {"name"=>{"$in"=>["a", "b"]}} +# end-in-merge + +# start-merge-reset +Band.in(name: ['a']).union.ne(name: 'c').in(name: ['b']) +# Interpreted query: +# {"name"=>{"$in"=>["a"], "$ne"=>"c"}, "$and"=>[{"name"=>{"$in"=>["b"]}}]} +# end-merge-reset + +# start-merge-where +Band.in(name: ['a']).union.where(name: {'$in' => 'b'}) +# Interpreted query: +# {"foo"=>{"$in"=>["a"]}, "$and"=>[{"foo"=>{"$in"=>"b"}}]} +# end-merge-where + +# start-range-query +Band.in(year: 1950..1960) +# Interpreted query: +# {"year"=>{"$in"=>[1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960]}} +# end-range-query + + diff --git a/source/interact-data.txt b/source/interact-data.txt index 424edf96..83247dcb 100644 --- a/source/interact-data.txt +++ b/source/interact-data.txt @@ -11,13 +11,13 @@ Interact with Data .. meta:: :keywords: ruby framework, odm, crud, query -.. TODO - .. toctree:: - :caption: Interact with Data - /interact-data/specify-query +.. toctree:: + :caption: Interact with Data + + /interact-data/specify-query In this section, you can learn how to use {+odm+} to interact with your MongoDB data. -.. - :ref:`mongoid-data-specify-query`: Learn how to construct -.. queries to match specific documents in a MongoDB collection. +- :ref:`mongoid-data-specify-query`: Learn how to construct + queries to match specific documents in a MongoDB collection. diff --git a/source/interact-data/specify-query.txt b/source/interact-data/specify-query.txt new file mode 100644 index 00000000..45270dab --- /dev/null +++ b/source/interact-data/specify-query.txt @@ -0,0 +1,476 @@ +.. _mongoid-data-specify-query: + +======= +Queries +======= + +.. facet:: + :name: genre + :values: reference + +.. meta:: + :keywords: ruby framework, odm, crud, filter + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +Overview +-------- + +In this guide, you can learn how to specify a **query** by using {+odm+}. + +You can refine the set of documents that a query returns by creating a +**query filter**. A query filter is an expression that specifies the search +criteria MongoDB uses to match documents in a read or write operation. +When creating a query filter, you can prompt the driver to search for +documents with an exact match to your query, or you can compose query +filters to express more complex matching criteria. + +{+odm+} provides a query DSL similar to the one used in Active Record. + +Sample Data +~~~~~~~~~~~ + +The examples in this guide use the ``Band`` model, which represents a +band or musical group. The definition of the ``Band`` model might be +different for each section to demonstrate different query +functionalities. Some sections might also use the ``Manager`` model, +which represents a person who manages a given band. + +``Show`` model, which +represents a live performance by a certain band or musical group. + +Queries in {+odm+} +------------------ + +{+odm+} query methods return ``Mongoid::Criteria`` objects, which are +chainable and lazily evaluated wrappers for the MongoDB Query API. +The queries are executed when you iterate through the results. The +following example demonstrates the return type for a simple query: + +.. code-block:: ruby + + # Creates a simple query + Band.where(name: "Deftones") + + # Returns a Criteria object + # => #"Deftones"} + # options: {} + # class: Band + # embedded: false> + + # Evaluate the query by converting to JSON + Band.where(name: "Deftones").to_json + + # Returns matching documents + # => [{"_id":"...","name":"Deftones"}] + +You can use methods such as ``first()`` and ``last()`` to return +individual documents. You can also iterate a ``Criteria`` object by using +methods such as ``each()`` or ``map()`` to retrieve documents from the +server. You can use ``to_json()`` to convert a ``Criteria`` object to +JSON. + +.. tip:: + + If you call more query methods on an existing ``Criteria`` object, + {+odm+} merges the filter criteria. + +Condition Syntax +---------------- + +This section describes the syntax patterns that you can use to create +filter criteria. You can specify queries in {+odm+} by using any of the +following syntax patterns: + +- Field syntax +- Query API syntax +- Symbol operator syntax + +.. note:: Query Syntax Behavior + + These syntaxes support querying embedded documents by using dot notation. + The syntaxes also respect :ref:`field aliases ` + and field types, if the field being queried is defined in the model class. + +The examples in this section use the following model definition: + +.. code-block:: ruby + + class Band + include Mongoid::Document + + field :name, type: String + field :founded, type: Integer + field :m, as: :member_count, type: Integer + + embeds_one :manager + end + + class Manager + include Mongoid::Document + + embedded_in :band + + field :name, type: String + end + +Field Syntax +~~~~~~~~~~~~ + +The field querying syntax uses the basic {+language+} hashes. The keys +can be symbols or strings and correspond to field names in MongoDB +documents. + +The following code shows two equivalent queries that use field querying +syntax to retrieve documents in which the ``name`` field value is +``'Depeche Mode'``: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-simple-field-query + :end-before: end-simple-field-query + :language: ruby + :dedent: + +Query API Syntax +~~~~~~~~~~~~~~~~ + +You can specify a Query API operator on any field by using the hash +syntax, as shown by the following equivalent queries: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-query-api-query + :end-before: end-query-api-query + :language: ruby + :dedent: + +Symbol Operator Syntax +~~~~~~~~~~~~~~~~~~~~~~ + +You can specify Query API operators as methods on symbols for the +respective field name, as shown in the following code: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-symbol-query + :end-before: end-symbol-query + :language: ruby + :dedent: + +Fields +------ + +This section describes how to perform queries on fields with different +types of values. + +Defined Fields +~~~~~~~~~~~~~~ + +.. TODO add link to Fields page + +To query on a field, the field does not need to be in the +the model class definition. However, if a field is defined in +the model class, {+odm+} coerces query values to match the defined field +types when constructing the query. + +The following code specifies a string value when querying on the +``founded`` field. Because the ``founded`` field is defined in the model +class to have ``Integer`` values, {+odm+} coerces the string ``'2020'`` +to ``2020`` when performing the query: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-defined-field-query + :end-before: end-defined-field-query + :language: ruby + :dedent: + +Raw Values +~~~~~~~~~~ + +To bypass {+odm+}'s query type coercion behavior and query +directly for the raw-typed value in the database, wrap the query value in +the ``Mongoid::RawValue`` class, as shown in the following code: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-raw-field-query + :end-before: end-raw-field-query + :language: ruby + :dedent: + +This behavior can be useful when working with legacy data. + +.. _mongoid-query-field-alias: + +Field Aliases +~~~~~~~~~~~~~ + +.. TODO update links + +Queries follow the :ref:`storage field names ` +and :ref:`field aliases ` that you might have set in your +model class definition. + +The ``id`` and ``_id`` fields are aliases, so you can use either field +name in queries: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-id-field-query + :end-before: end-id-field-query + :language: ruby + :dedent: + +Embedded Documents +~~~~~~~~~~~~~~~~~~ + +To query on values of fields of embedded documents, you can use dot +notation. The following code retrieves documents in which the ``name`` +field of the embedded ``Manager`` document is ``'Smith'``: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-embedded-query + :end-before: end-embedded-query + :language: ruby + :dedent: + +The following code demonstrates how to use a symbol operator when +querying on an embedded field: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-embedded-ne-query + :end-before: end-embedded-ne-query + :language: ruby + :dedent: + +.. note:: + + Queries always return top-level model instances, even if all of the + conditions reference embedded document fields. + +.. _mongoid-query-logical-operations: + +Logical Operations +------------------ + +{+odm+} supports ``and()``, ``or()``, ``nor()``, and ``not()`` logical +operations on ``Criteria`` objects. These methods take one or more hashes +of conditions or another ``Criteria`` object as their arguments. The +``not`` operation has an argument-free version. + +The following code demonstrates how to use the logical operations in +queries: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-logical-ops + :end-before: end-logical-ops + :language: ruby + :dedent: + +.. note:: Array Parameters + + To ensure backwards compatibility with earlier {+odm+} versions, the + logical operation methods accept arrays of parameters, which are + flattened to obtain the criteria. + + Passing arrays to logical operations is deprecated and may be removed + in a future version. + +The following queries produce the same conditions: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-logical-and-ops + :end-before: end-logical-and-ops + :language: ruby + :dedent: + +Operator Combinations +~~~~~~~~~~~~~~~~~~~~~ + +The logical operators have the the same semantics as those from Active +Record. + +When conditions are specified on the same field multiple times, all +conditions are added to the criteria, as shown by the queries in the +following code: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-logical-combination-ops + :end-before: end-logical-combination-ops + :language: ruby + :dedent: + +The ``any_of()``, ``none_of()``, ``nor()``, and ``not()`` operations +behave similarly. + +When you use ``and()``, ``or()``, and ``nor()`` logical operators, they +operate on the criteria built up to that point: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-logical-combination-ops-2 + :end-before: end-logical-combination-ops-2 + :language: ruby + :dedent: + +not() Behavior +~~~~~~~~~~~~~~ + +You can use the ``not()`` method without arguments, in which case it +negates the next condition that is specified. The ``not()`` method can +be called with one or more hash conditions or ``Criteria`` objects, +which are all negated and added to the criteria. + +The following examples demonstrate the behavior of ``not()``: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-not-logical + :end-before: end-not-logical + :language: ruby + :dedent: + +.. note:: + + You cannot use the ``$not`` operator in MongoDB with a string argument. + Mongoid uses the ``$ne`` operator to achieve negation: + + .. literalinclude:: /includes/interact-data/query.rb + :start-after: start-not-logical-note + :end-before: end-not-logical-note + :language: ruby + :dedent: + +Similarly to ``and()``, the ``not()`` operation negates individual +conditions for simple field criteria. For complex conditions and when a +field already has a condition defined on it, {+odm+} emulates ``$not`` +by using an ``{'$and' => [{'$nor' => ...}]}`` construct, since MongoDB +only supports the ``$not`` operator on a per-field basis rather than +globally: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-not-behavior + :end-before: end-not-behavior + :language: ruby + :dedent: + +If you are using ``not()`` with arrays or regular expressions, view the +limitations of ``$not`` in the :manual:`{+server-manual+} +`. + +Incremental Query Construction +------------------------------ + +By default, when you add conditions to a query, {+odm+} considers each +condition complete and independent from any other conditions +present in the query. For example, calling ``in()`` twice adds two separate +``$in`` conditions: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-incremental-1 + :end-before: end-incremental-1 + :language: ruby + :dedent: + +Some operator methods support building the condition incrementally. In this +case, when adding a condition which uses one of the supported operators, +if there already is a condition on the same field using the +same operator, the operator expressions are combined according to the +specified *merge strategy*, which is described in the following section. + +.. _mongoid-merge-strategies: + +Merge Strategies +~~~~~~~~~~~~~~~~ + +{+odm+} provides the following merge strategies: + +- **Override**: The new operator instance replaces any existing + conditions on the same field by using the same operator. +- **Intersect**: If there already is a condition using the same operator + on the same field, the values of the existing condition are + intersected with the values of the new condition and the result is + stored as the operator value. +- **Union**: If there already is a condition using the same operator on + the same field, the values of the new condition are added to the + values of the existing condition and the result is stored as the + operator value. + +The following code demonstrates hwo the merge strategies produce +criteria, by using ``in()`` as the example operator: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-in-merge + :end-before: end-in-merge + :language: ruby + :dedent: + +The strategy is requested by calling ``override()``, ``intersect()`` or ``union()`` +on a ``Criteria`` instance. The requested strategy applies to the next +condition method called on the query. If the next condition method called does +not support merge strategies, the strategy is reset, as shown in the following +example: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-merge-reset + :end-before: end-merge-reset + :language: ruby + :dedent: + +Since ``ne()`` does not support merge strategies, the ``union`` strategy +is ignored and reset, then when ``in()`` is invoked the second time, +there is no active strategy. + +.. warning:: + + Merge strategies assume that the previous conditions have been added + to the top level of the query. However, this is not always the case, + as conditions may be nested under an ``$and`` clause. Using merge + strategies with complex criteria generate incorrect queries. + +Supported Operator Methods +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following operator methods support merge strategies: + +- ``all()`` +- ``in()`` +- ``nin()`` + +The set of methods may be expanded in future releases of {+odm+}. To ensure +future compatibility, invoke a strategy method only when the next method call +is an operator that supports merge strategies. + +Merge strategies are currently applied only when conditions are +added through the designated methods. In the following example, the +merge strategy is not applied because the second condition is added as +``where()``, not by using ``in()``: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-merge-where + :end-before: end-merge-where + :language: ruby + :dedent: + +Operator Value Expansion +~~~~~~~~~~~~~~~~~~~~~~~~ + +Operator methods that support merge strategies take ``Array`` as their +value type. {+odm+} expands ``Array``-compatible types, such as a +``Range``, when they are used with these operator methods. + +The following example demonstrates how you can pass a ``Range`` object +as the query value in when calling ``in()``: + +.. literalinclude:: /includes/interact-data/query.rb + :start-after: start-range-query + :end-before: end-range-query + :language: ruby + :dedent: + +{+odm+} wraps non-``Array`` values in arrays, +as the shown in the following example: + +.. code-block:: ruby + + Band.in(year: 1950) + # Interpreted query: {"year"=>{"$in"=>[1950]}} From d8469d9d5be5c09816f74400b42ce4a472d20e34 Mon Sep 17 00:00:00 2001 From: rustagir Date: Tue, 29 Oct 2024 10:38:40 -0400 Subject: [PATCH 2/6] vale --- source/interact-data/specify-query.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/interact-data/specify-query.txt b/source/interact-data/specify-query.txt index 45270dab..f8600413 100644 --- a/source/interact-data/specify-query.txt +++ b/source/interact-data/specify-query.txt @@ -246,7 +246,7 @@ querying on an embedded field: .. note:: - Queries always return top-level model instances, even if all of the + Queries always return top-level model instances, even if all the conditions reference embedded document fields. .. _mongoid-query-logical-operations: @@ -440,7 +440,7 @@ The set of methods may be expanded in future releases of {+odm+}. To ensure future compatibility, invoke a strategy method only when the next method call is an operator that supports merge strategies. -Merge strategies are currently applied only when conditions are +Merge strategies are applied only when conditions are added through the designated methods. In the following example, the merge strategy is not applied because the second condition is added as ``where()``, not by using ``in()``: From 5fa165a497132c3c0344fccd37b45ff7dac03cc3 Mon Sep 17 00:00:00 2001 From: rustagir Date: Tue, 29 Oct 2024 10:39:49 -0400 Subject: [PATCH 3/6] title --- source/interact-data/specify-query.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/interact-data/specify-query.txt b/source/interact-data/specify-query.txt index f8600413..bdd74d76 100644 --- a/source/interact-data/specify-query.txt +++ b/source/interact-data/specify-query.txt @@ -1,8 +1,8 @@ .. _mongoid-data-specify-query: -======= -Queries -======= +=============== +Specify a Query +=============== .. facet:: :name: genre From 4b4e05835cefc09ae71851f45a61acd7ef249924 Mon Sep 17 00:00:00 2001 From: rustagir Date: Tue, 29 Oct 2024 12:25:17 -0400 Subject: [PATCH 4/6] code edits --- source/includes/interact-data/query.rb | 33 +++++++++++++------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/source/includes/interact-data/query.rb b/source/includes/interact-data/query.rb index 2e6046fb..a92317ef 100644 --- a/source/includes/interact-data/query.rb +++ b/source/includes/interact-data/query.rb @@ -1,6 +1,6 @@ # start-simple-field-query Band.where(name: 'Depeche Mode') -Band.where(name => 'Depeche Mode') +Band.where('name' => 'Depeche Mode') # end-simple-field-query # start-query-api-query @@ -68,53 +68,54 @@ # start-logical-combination-ops # Combines as "and" -Band.where(name: 'Swans').where(name: 'Feist').selector +Band.where(name: 'Swans').where(name: 'Feist') # Combines as "or" -Band.where(name: 'Swans').or(name: 'Feist').selector +Band.where(name: 'Swans').or(name: 'Feist') # end-logical-combination-ops # start-logical-combination-ops-2 # "or" applies to the first condition, and the second is combined # as "and" -Band.or(name: 'Sun').where(label: 'Trust').selector +Band.or(name: 'Sun').where(label: 'Trust') -# Same as previous example - where and and are aliases -Band.or(name: 'Sun').and(label: 'Trust').selector +# Same as previous example - "where" and "and" are aliases +Band.or(name: 'Sun').and(label: 'Trust') # Same operator can be stacked any number of times -Band.or(name: 'Sun').or(label: 'Trust').selector +Band.or(name: 'Sun').or(label: 'Trust') # The last label condition is added to the top level as "and" -Band.where(name: 'Sun').or(label: 'Trust').where(label: 'Feist').selector -# => {"$or"=>[{"name"=>"Sun"}, {"label"=>"Trust"}], "label"=>"Foo"} +Band.where(name: 'Sun').or(label: 'Trust').where(label: 'Feist') +# Interpreted query: +# {"$or"=>[{"name"=>"Sun"}, {"label"=>"Trust"}], "label"=>"Feist"} # end-logical-combination-ops-2 # start-not-logical # "not" negates "where" -Band.not.where(name: 'Best').selector +Band.not.where(name: 'Best') # The second "where" is added as "$and" -Band.not.where(name: 'Best').where(label: /Records/).selector +Band.not.where(name: 'Best').where(label: /Records/) # "not" negates its argument -Band.not(name: 'Best').selector +Band.not(name: 'Best') # end-not-logical # start-not-logical-note # String negation - uses "$ne" -Band.not.where(name: 'Best').selector +Band.not.where(name: 'Best') # Regex negation - uses "$not" -Band.not.where(name: /Best/).selector +Band.not.where(name: /Best/) # end-not-logical-note # start-not-behavior # Simple condition -Band.not(name: /Best/).selector +Band.not(name: /Best/) # Complex conditions -Band.where(name: /Best/).not(name: 'Astral Projection').selector +Band.where(name: /Best/).not(name: 'Astral Projection') # Symbol operator syntax Band.not(:name.ne => 'Astral Projection') From 7a5479f0f3de1e4b11e94c1ea7db80227ea01888 Mon Sep 17 00:00:00 2001 From: rustagir Date: Wed, 30 Oct 2024 14:03:42 -0400 Subject: [PATCH 5/6] JS PR fixes 1 --- source/includes/interact-data/query.rb | 3 +- source/interact-data/specify-query.txt | 71 ++++++++++++++------------ 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/source/includes/interact-data/query.rb b/source/includes/interact-data/query.rb index a92317ef..d2aa70b5 100644 --- a/source/includes/interact-data/query.rb +++ b/source/includes/interact-data/query.rb @@ -22,6 +22,7 @@ # start-id-field-query Band.where(id: '5ebdeddfe1b83265a376a760') +Band.where(_id: '5ebdeddfe1b83265a376a760') # end-id-field-query # start-embedded-query @@ -53,7 +54,7 @@ # Multiple conditions in the same "and" call Band.and({name: 'Sun Kil Moon'}, {member_count: 2}) -# Multiple conditions in an array - Deprecates +# Multiple conditions in an array - Deprecated Band.and([{name: 'Sun Kil Moon'}, {member_count: 2}]) # Condition in "where" and a scope diff --git a/source/interact-data/specify-query.txt b/source/interact-data/specify-query.txt index bdd74d76..d09c0923 100644 --- a/source/interact-data/specify-query.txt +++ b/source/interact-data/specify-query.txt @@ -9,7 +9,7 @@ Specify a Query :values: reference .. meta:: - :keywords: ruby framework, odm, crud, filter + :keywords: ruby framework, odm, crud, filter, code example .. contents:: On this page :local: @@ -29,7 +29,8 @@ When creating a query filter, you can prompt the driver to search for documents with an exact match to your query, or you can compose query filters to express more complex matching criteria. -{+odm+} provides a query DSL similar to the one used in Active Record. +{+odm+} provides a query domain-specific language (DSL) similar to the +one used in Active Record. Sample Data ~~~~~~~~~~~ @@ -38,9 +39,7 @@ The examples in this guide use the ``Band`` model, which represents a band or musical group. The definition of the ``Band`` model might be different for each section to demonstrate different query functionalities. Some sections might also use the ``Manager`` model, -which represents a person who manages a given band. - -``Show`` model, which +which represents a person who manages a given band, or a ``Show`` model, which represents a live performance by a certain band or musical group. Queries in {+odm+} @@ -75,13 +74,13 @@ methods such as ``each()`` or ``map()`` to retrieve documents from the server. You can use ``to_json()`` to convert a ``Criteria`` object to JSON. -.. tip:: +.. tip:: Chaining methods - If you call more query methods on an existing ``Criteria`` object, + If you chain other query methods on an existing ``Criteria`` object, {+odm+} merges the filter criteria. -Condition Syntax ----------------- +Create a Query Filter +--------------------- This section describes the syntax patterns that you can use to create filter criteria. You can specify queries in {+odm+} by using any of the @@ -91,7 +90,7 @@ following syntax patterns: - Query API syntax - Symbol operator syntax -.. note:: Query Syntax Behavior +.. note:: Syntax Behaviors These syntaxes support querying embedded documents by using dot notation. The syntaxes also respect :ref:`field aliases ` @@ -160,8 +159,8 @@ respective field name, as shown in the following code: :language: ruby :dedent: -Fields ------- +Query on Different Field Types +------------------------------ This section describes how to perform queries on fields with different types of values. @@ -200,8 +199,6 @@ the ``Mongoid::RawValue`` class, as shown in the following code: :language: ruby :dedent: -This behavior can be useful when working with legacy data. - .. _mongoid-query-field-alias: Field Aliases @@ -254,10 +251,17 @@ querying on an embedded field: Logical Operations ------------------ -{+odm+} supports ``and()``, ``or()``, ``nor()``, and ``not()`` logical -operations on ``Criteria`` objects. These methods take one or more hashes -of conditions or another ``Criteria`` object as their arguments. The -``not`` operation has an argument-free version. +{+odm+} supports the following logical operations on ``Criteria`` +objects: + +- ``and()`` +- ``or()`` +- ``nor()`` +- ``not()`` + +These methods take one or more hashes of conditions or another +``Criteria`` object as their arguments. The ``not()`` operation has an +argument-free version. The following code demonstrates how to use the logical operations in queries: @@ -274,7 +278,7 @@ queries: logical operation methods accept arrays of parameters, which are flattened to obtain the criteria. - Passing arrays to logical operations is deprecated and may be removed + Passing arrays to logical operations is deprecated and might be removed in a future version. The following queries produce the same conditions: @@ -343,8 +347,8 @@ The following examples demonstrate the behavior of ``not()``: Similarly to ``and()``, the ``not()`` operation negates individual conditions for simple field criteria. For complex conditions and when a field already has a condition defined on it, {+odm+} emulates ``$not`` -by using an ``{'$and' => [{'$nor' => ...}]}`` construct, since MongoDB -only supports the ``$not`` operator on a per-field basis rather than +by using an ``{'$and' => [{'$nor' => ...}]}`` construct, because MongoDB +supports the ``$not`` operator only on a per-field basis rather than globally: .. literalinclude:: /includes/interact-data/query.rb @@ -371,11 +375,12 @@ present in the query. For example, calling ``in()`` twice adds two separate :language: ruby :dedent: -Some operator methods support building the condition incrementally. In this -case, when adding a condition which uses one of the supported operators, -if there already is a condition on the same field using the -same operator, the operator expressions are combined according to the -specified *merge strategy*, which is described in the following section. +Some operator methods support building the condition incrementally. When +you add a condition which uses one of the supported operators, {+odm+} +sees if there already is a condition on the same field using the +same operator. If so, the operator expressions are combined according to the +specified *merge strategy*. The following section describes the available merge +strategies. .. _mongoid-merge-strategies: @@ -395,8 +400,8 @@ Merge Strategies values of the existing condition and the result is stored as the operator value. -The following code demonstrates hwo the merge strategies produce -criteria, by using ``in()`` as the example operator: +The following code demonstrates how the merge strategies produce +criteria by using ``in()`` as the example operator: .. literalinclude:: /includes/interact-data/query.rb :start-after: start-in-merge @@ -416,7 +421,7 @@ example: :language: ruby :dedent: -Since ``ne()`` does not support merge strategies, the ``union`` strategy +Because ``ne()`` does not support merge strategies, the ``union`` strategy is ignored and reset, then when ``in()`` is invoked the second time, there is no active strategy. @@ -424,8 +429,8 @@ there is no active strategy. Merge strategies assume that the previous conditions have been added to the top level of the query. However, this is not always the case, - as conditions may be nested under an ``$and`` clause. Using merge - strategies with complex criteria generate incorrect queries. + as conditions might be nested under an ``$and`` clause. Using merge + strategies with complex criteria can generate incorrect queries. Supported Operator Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -436,7 +441,7 @@ The following operator methods support merge strategies: - ``in()`` - ``nin()`` -The set of methods may be expanded in future releases of {+odm+}. To ensure +The set of methods might be expanded in future releases of {+odm+}. To ensure future compatibility, invoke a strategy method only when the next method call is an operator that supports merge strategies. @@ -459,7 +464,7 @@ value type. {+odm+} expands ``Array``-compatible types, such as a ``Range``, when they are used with these operator methods. The following example demonstrates how you can pass a ``Range`` object -as the query value in when calling ``in()``: +as the query value when using the ``in()`` method: .. literalinclude:: /includes/interact-data/query.rb :start-after: start-range-query From f722f7796025ef6586b86c18c1f30f185b1e9171 Mon Sep 17 00:00:00 2001 From: rustagir Date: Wed, 30 Oct 2024 14:04:24 -0400 Subject: [PATCH 6/6] fix --- source/interact-data/specify-query.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/interact-data/specify-query.txt b/source/interact-data/specify-query.txt index d09c0923..63ed1b74 100644 --- a/source/interact-data/specify-query.txt +++ b/source/interact-data/specify-query.txt @@ -422,7 +422,7 @@ example: :dedent: Because ``ne()`` does not support merge strategies, the ``union`` strategy -is ignored and reset, then when ``in()`` is invoked the second time, +is ignored and reset. Then, when ``in()`` is invoked the second time, there is no active strategy. .. warning::