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.



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
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
# File 'lib/parse/query/constraints.rb', line 2842

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:



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

register :equals_linked_pointer