Class: Parse::Constraint::PointerEqualsLinkedPointerConstraint

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

Overview

A constraint for comparing pointer fields through linked objects using MongoDB aggregation. This allows comparing ObjectA.field1 with ObjectA.linkedObject.field2 where both are pointers.

# Find ObjectA where ObjectA.author equals ObjectA.project.owner
ObjectA.where(:author.equals_linked_pointer => { through: :project, field: :owner })

# This generates a MongoDB aggregation pipeline with $lookup and $expr
# to compare pointer fields across linked documents

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.

Returns:

  • (Hash)

    the compiled constraint.



2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
# File 'lib/parse/query/constraints.rb', line 2811

def build
  unless @value.is_a?(Hash) && @value[:through] && @value[:field]
    raise ArgumentError, "equals_linked_pointer requires: { through: :linked_field, field: :target_field }"
  end

  through_field = @value[:through]
  target_field = @value[:field]
  local_field = @operation.operand

  # Format field names according to Parse conventions
  # Pointer fields in MongoDB are stored with _p_ prefix
  formatted_through = "_p_" + Parse::Query.format_field(through_field)
  formatted_target = "_p_" + Parse::Query.format_field(target_field)
  formatted_local = "_p_" + Parse::Query.format_field(local_field)

  # Determine the target collection name from the through field
  # Use classify to convert field name to class name (e.g., :project -> "Project")
  target_collection = through_field.to_s.classify

  # Build the aggregation pipeline
  # Use clean alias name without _p_ prefix for readability
  lookup_alias = "#{through_field.to_s.camelize(:lower)}_data"

  # Parse stores pointers as "ClassName$objectId" strings
  # We need to extract just the objectId part after the $
  pipeline = [
    {
      "$addFields" => {
        "#{formatted_through}_id" => {
          "$substr" => [
            "$#{formatted_through}",
            target_collection.length + 1,  # Skip "ClassName$"
            -1,  # Rest of string
          ],
        },
      },
    },
    {
      "$lookup" => {
        "from" => target_collection,
        "localField" => formatted_through,
        "foreignField" => "_id",
        "as" => lookup_alias,
      },
    },
    {
      "$match" => {
        "$expr" => {
          "$eq" => [
            { "$arrayElemAt" => ["$#{lookup_alias}.#{formatted_target}", 0] },
            "$#{formatted_local}",
          ],
        },
      },
    },
  ]

  # Return a special marker that indicates this needs aggregation pipeline processing
  { "__aggregation_pipeline" => pipeline }
end

#equals_linked_pointerPointerEqualsLinkedPointerConstraint

A registered method on a symbol to create the constraint.

Examples:

q.where :field.equals_linked_pointer => { through: :linked_field, field: :target_field }

Returns:



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

register :equals_linked_pointer