Class: Parse::Constraint::ArrayEqConstraint

Inherits:
Parse::Constraint show all
Defined in:
lib/parse/query/constraints.rb

Overview

Note:

This constraint uses aggregation pipeline with MongoDB $eq on arrays.

Exact array equality constraint using MongoDB aggregation with $eq. Matches arrays that are exactly equal, including element order. This is order-dependent matching: [A, B] does NOT match [B, A].

q.where :field.eq_array => ["rock", "pop"] q.where :tags.eq_array => [category1, category2] # for pointers

For pointer arrays (has_many relations), pass Parse objects or pointers. The constraint will automatically extract objectIds for comparison.

Instance Attribute Summary

Attributes inherited from Parse::Constraint

#operand, #operation, #operator, #value

Instance Method Summary collapse

Methods inherited from Parse::Constraint

#as_json, constraint_keyword, create, formatted_value, #formatted_value, #initialize, #key, #precedence, register, #to_s

Constructor Details

This class inherits a constructor from Parse::Constraint

Instance Method Details

#buildHash

Returns the compiled constraint using aggregation pipeline.

Returns:

  • (Hash)

    the compiled constraint using aggregation pipeline.



962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
# File 'lib/parse/query/constraints.rb', line 962

def build
  val = formatted_value
  val = [val].compact unless val.is_a?(Array)

  field_name = Parse::Query.format_field(@operation.operand)

  # Check if values are pointers (Parse objects or pointer objects)
  is_pointer_array = val.any? do |item|
    item.respond_to?(:pointer) || item.is_a?(Parse::Pointer)
  end

  if is_pointer_array
    # Extract objectIds from pointers for comparison
    target_ids = val.map do |item|
      if item.respond_to?(:id)
        item.id
      elsif item.is_a?(Parse::Pointer)
        item.id
      else
        item
      end
    end

    # Validate all IDs are present (unsaved objects have nil IDs)
    if target_ids.any?(&:nil?)
      raise ArgumentError, "#{self.class.name}: Cannot use unsaved objects (missing ID) in array constraint"
    end

    # For pointer arrays, compare mapped objectIds with exact equality (order matters).
    # $ifNull coerces a missing/null field to [] so $map doesn't raise a type
    # error on legacy documents that lack the field.
    pipeline = [
      {
        "$match" => {
          "$expr" => {
            "$eq" => [
              { "$map" => {
                  "input" => { "$ifNull" => ["$#{field_name}", []] },
                  "as" => "p",
                  "in" => "$$p.objectId",
                } },
              target_ids,
            ],
          },
        },
      },
    ]
  else
    # For simple value arrays, direct $eq comparison (order matters).
    # $ifNull coerces a missing/null field to [] so a doc lacking the field
    # is treated the same as one with [], consistent with set_equals/arr_empty.
    pipeline = [
      {
        "$match" => {
          "$expr" => {
            "$eq" => [
              { "$ifNull" => ["$#{field_name}", []] },
              val,
            ],
          },
        },
      },
    ]
  end

  { "__aggregation_pipeline" => pipeline }
end

#eq_arrayArrayEqConstraint

Note:

Use :eq_array for explicit array equality matching. Simple :eq is handled by the base Constraint class for scalar equality.

A registered method on a symbol to create the constraint.

Examples:

q.where :field.eq_array => ["value1", "value2"]
q.where :categories.eq_array => [cat1, cat2]

Returns:



959
# File 'lib/parse/query/constraints.rb', line 959

register :eq_array