class MongoQL::Stage::Lookup

Attributes

as[RW]
condition[RW]
ctx[RW]
from[RW]
let_vars[RW]
nested_pipeline[RW]
nested_pipeline_block[RW]

Public Class Methods

new(ctx, from, condition = nil, on: nil, as: nil, &block) click to toggle source
# File lib/mongo_ql/stage/lookup.rb, line 38
def initialize(ctx, from, condition = nil, on: nil, as: nil, &block)
  @ctx       = ctx
  @from      = collection_name(from)
  @as        = new_array_name(as)
  @nested_pipeline_block = block

  if has_nested_pipeline?
    @let_vars = NestedPipelineVars.new
    @nested_pipeline = eval_nested_pipeline
  else
    @condition = condition_ast(condition || on)
  end
end

Public Instance Methods

to_ast() click to toggle source
# File lib/mongo_ql/stage/lookup.rb, line 52
def to_ast
  lookup_expr = { "from" => from, "as" => as }
  if has_nested_pipeline?
    lookup_expr["pipeline"] = nested_pipeline
    lookup_expr["let"]      = let_vars.vars
  else
    lookup_expr = lookup_expr.merge(condition)
  end
  ast = { "$lookup" => lookup_expr }
  MongoQL::Utils.deep_transform_values(ast, &MongoQL::EXPRESSION_TO_AST_MAPPER)
end

Private Instance Methods

collection_name(from) click to toggle source
# File lib/mongo_ql/stage/lookup.rb, line 75
def collection_name(from)
  case from
  when String, Symbol
    from
  when Expression::FieldNode
    from.to_s
  else
    if from&.respond_to?(:collection)
      from&.collection&.name
    elsif from&.respond_to?(:field_name)
      from.field_name
    else
      raise ArgumentError, "#{from} is not a valid collection"
    end
  end
end
condition_ast(cond) click to toggle source
# File lib/mongo_ql/stage/lookup.rb, line 92
def condition_ast(cond)
  raise ArgumentError, "#{cond.inspect} must be a valid Expression::Binary, example: _id == user_id" unless cond.is_a?(Expression::Binary)
  raise ArgumentError, "#{cond.inspect} must be an 'equal' expression, example: _id == user_id" unless cond.operator == "$eq"
  {
    "localField"   => cond&.left_node&.to_s,
    "foreignField" => cond&.right_node&.to_s
  }
end
eval_nested_pipeline() click to toggle source
# File lib/mongo_ql/stage/lookup.rb, line 69
def eval_nested_pipeline
  sub_ctx = StageContext.new
  sub_ctx.instance_exec(let_vars, &nested_pipeline_block)
  sub_ctx
end
has_nested_pipeline?() click to toggle source
# File lib/mongo_ql/stage/lookup.rb, line 65
def has_nested_pipeline?
  condition.nil? && !nested_pipeline_block.nil?
end
new_array_name(as) click to toggle source
# File lib/mongo_ql/stage/lookup.rb, line 101
def new_array_name(as)
  as&.to_s
end