Shard-side merge of a sharded $search query loses SEARCH_META metadata cursors

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • Query Integration
    • ALL
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      When mongos delegates the merging half of a sharded $search query that references $$SEARCH_META to a shard, the metadata $mergeCursors that mongos injected into the $setVariableFromSubPipeline sub-pipeline does not survive serialization to the merging shard. The shard reparses the sub-pipeline as the bare planShardedSearch metaPipeline (e.g. [$group, $facet, $replaceRoot]), whose front stage requires an input source, and the first doGetNext() hits tripwire 6448002 ("Expected to have already attached a cursor source to the pipeline"), failing the query.

      Mechanism

      * cluster_aggregation_planner.cpp: partitionAndAddMergeCursorsSource() runs before the merge-location decision, injecting the data cursors as a top-level $mergeCursors and the metadata cursors into the $setVariableFromSubPipeline sub-pipeline (injectMetaCursor in sharded_agg_helpers.cpp).
      * When the merge is delegated (createCommandForMergingShard), the top-level data $mergeCursors serializes with its remotes, but the sub-pipeline's injected initial source is dropped -- the production-captured command (see AF-18751) shows the bare metaPipeline.
      * On the shard, DocumentSourceSetVariableFromSubPipeline::createFromBson reparses the sub-pipeline; nothing reattaches a cursor source; tassert 6448002 fires on first execution.

      Reproduction

      Deterministic shard-side repro attached (af18751_repro.js): replays the captured merging-command shape directly against an 8.0 shard (internal-client hello; no mongot required). Fails with 6448002 on stock 8.0.27 binaries.

      The router-side trigger (what makes mongos choose shard-merge for a SEARCH_META pipeline) was not reproduced locally: after meta-cursor injection the merge pipeline reports required-to-run-on-router in a 2-shard mongotmock fixture, overriding both internalQueryProhibitMergingOnMongoS and $_internalSplitPipeline. The production occurrence (3-shard cluster, single targeted remote, secondaryPreferred, allowDiskUse, metaPipeline containing $facet) evidently reached a delegating dispatch path -- identifying it is part of this ticket.

      Fix directions

      Either (a) make the setVariable sub-pipeline's cursor source survive the mongos->shard hop (serialize + reattach, as the top-level $mergeCursors does), or (b) make SEARCH_META merge pipelines explicitly router-only in the dispatch decision so delegation cannot occur.

      Acceptance criteria

      The attached repro shape no longer trips 6448002 (either executes correctly with merged metadata or fails with a clean, non-tripwire error), plus a regression test covering the end-to-end router path once identified.

            Assignee:
            Mariano Shaar
            Reporter:
            Mariano Shaar
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: