Skip to content

Commit a692400

Browse files
authored
MONGOID-5453 Add .none_of query method (#5524)
* "none_of" query method * update docs and release notes * fix underline for header
1 parent 6f84371 commit a692400

File tree

4 files changed

+490
-2
lines changed

4 files changed

+490
-2
lines changed

docs/reference/queries.txt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ conditions are added to the criteria:
324324
Band.where(name: 1).or(name: 2).selector
325325
# => {"$or"=>[{"name"=>"1"}, {"name"=>"2"}]}
326326

327-
``any_of``, ``nor`` and ``not`` behave similarly, with ``not`` producing
327+
``any_of``, ``none_of``, ``nor`` and ``not`` behave similarly, with ``not`` producing
328328
different query shapes as described below.
329329

330330
When ``and``, ``or`` and ``nor`` logical operators are used, they
@@ -425,6 +425,20 @@ The conditions are hoisted to the top level if possible:
425425
# => {"label"=>/Trust/, "name"=>"Astral Projection"}
426426

427427

428+
.. _none-of:
429+
430+
``none_of`` Behavior
431+
--------------------
432+
433+
``none_of`` adds a negated disjunction ("nor") built from its arguments to
434+
the existing conditions in the criteria. For example:
435+
436+
.. code-block:: ruby
437+
438+
Band.where(label: /Trust/).none_of({name: 'Astral Projection'}, {name: /Best/})
439+
# => {"label"=>/Trust/, "$nor"=>[{"name"=>"Astral Projection"}, {"name"=>/Best/}]}
440+
441+
428442
``not`` Behavior
429443
----------------
430444

docs/release-notes/mongoid-8.1.txt

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,4 +371,30 @@ example:
371371
# => <Band _id: 633c74113282a438a15d2b56, name: "Death Cab For Cutie">
372372

373373
See the section on :ref:`Hash Assignment on Embedded Associations <hash-assignment>`
374-
for more details
374+
for more details
375+
376+
377+
Added ``none_of`` Query Method
378+
------------------------------
379+
380+
With the addition of ``none_of``, Mongoid 8.1 allows queries to exclude
381+
conditions in bulk. The emitted query will encapsulate the specified
382+
criteria in a ``$nor`` operation. For example:
383+
384+
.. code:: ruby
385+
386+
class Building
387+
include Mongoid::Document
388+
field :city, type: String
389+
field :height, type: Integer
390+
field :purpose, type: String
391+
field :occupancy, type: Integer
392+
end
393+
394+
Building.where(city: 'Portland').
395+
none_of(:height.lt => 100,
396+
:purpose => 'apartment',
397+
:occupancy.gt => 2500)
398+
399+
This would query all buildings in Portland, excluding apartments, buildings less than
400+
100 units tall, and buildings with an occupancy greater than 2500 people.

lib/mongoid/criteria/queryable/selectable.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,35 @@ def not(*criteria)
581581
end
582582
key :not, :override, "$not"
583583

584+
# Negate the arguments, constraining the query to only those documents
585+
# that do NOT match the arguments.
586+
#
587+
# @example Exclude a single criterion.
588+
# selectable.none_of(name: /Bob/)
589+
#
590+
# @example Exclude multiple criteria.
591+
# selectable.none_of(name: /Bob/, country: "USA")
592+
#
593+
# @example Exclude multiple criteria as an array.
594+
# selectable.none_of([{ name: /Bob/ }, { country: "USA" }])
595+
#
596+
# @param [ [ Hash | Criteria ]... ] *criteria The key/value pair
597+
# matches or Criteria objects to negate.
598+
#
599+
# @return [ Selectable ] The new selectable.
600+
def none_of(*criteria)
601+
criteria = _mongoid_flatten_arrays(criteria)
602+
return dup if criteria.empty?
603+
604+
exprs = criteria.map do |criterion|
605+
_mongoid_expand_keys(
606+
criterion.is_a?(Selectable) ?
607+
criterion.selector : criterion)
608+
end
609+
610+
self.and('$nor' => exprs)
611+
end
612+
584613
# Creates a disjunction using $or from the existing criteria in the
585614
# receiver and the provided arguments.
586615
#

0 commit comments

Comments
 (0)