Class: Parse::Constraint::PointerEqualsLinkedPointerConstraint

Inherits:
Constraint
  • Object
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 Method Summary collapse

Instance Method Details

#buildHash

Returns the compiled constraint.

Returns:

  • (Hash)

    the compiled constraint.



3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
# File 'lib/parse/query/constraints.rb', line 3079

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:



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

register :equals_linked_pointer