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.



933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
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
# File 'lib/parse/query/constraints.rb', line 933

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:



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

register :eq_array