Files
mongo/jstests/sharding/query/lookup_from_config_cache_chunks.js
Steve McClure 1ffbc6c2e9 SERVER-109432: Autofix JS var usage to favor let (#40637)
GitOrigin-RevId: 9674b7db36a0f3f650d39c1e3fb2ad6ff2141cfb
2025-08-28 19:21:01 +00:00

125 lines
4.2 KiB
JavaScript

/**
* With standard $lookup syntax, the "from" collection is always interpreted to be in the same
* database the aggregate command is run on. Additionally, the merging is always done on the primary
* shard for the database.
*
* This tests alternative $lookup syntax that supports reading from an unsharded collection that has
* identical contents across all shards (specifically config.cache.chunks.* namespaces). With the
* alternative syntax, $lookup behavior changes and it is run locally on each shard rather than
* merged on the primary shard for the database.
*
* Alternative $lookup syntax:
* {$lookup: {from: {db:<>, coll:<>},...}}
*/
import {assertErrorCode} from "jstests/aggregation/extras/utils.js";
import {DiscoverTopology} from "jstests/libs/discover_topology.js";
import {ShardingTest} from "jstests/libs/shardingtest.js";
import {flushRoutersAndRefreshShardMetadata} from "jstests/sharding/libs/sharded_transactions_helpers.js";
const st = new ShardingTest({shards: 2});
const dbName = jsTestName();
const collName = "foo";
let chunksCollName;
const shard0DB = st.shard0.getDB(dbName);
const shard1DB = st.shard1.getDB(dbName);
const sourceCollection = st.s0.getDB(dbName)[collName];
// Sets up the data for $lookup on config.cache.chunks.* namespaces.
const setUp = () => {
sourceCollection.drop();
// Set up sourceCollection to be sharded on {x:1} and to have the following distribution:
// shard0: [MinKey, 0)
// shard1: [0, MaxKey)
st.shardColl(sourceCollection, {x: 1}, {x: 0}, {x: 0}, dbName);
// Insert a corresponding entry in sourceCollection for each document in
// config.cache.chunks.collUuid.
assert.commandWorked(sourceCollection.insert({x: MinKey}));
assert.commandWorked(sourceCollection.insert({x: 0}));
const collNs = dbName + "." + collName;
const collEntry = st.config.collections.findOne({_id: collNs});
chunksCollName = "cache.chunks." + collNs;
flushRoutersAndRefreshShardMetadata(st, {collNs});
};
// $lookup alternative syntax only supports reading 'from' config.cache.chunks.* namespaces.
const invalidLookups = [
{
$lookup: {
from: {db: "config", coll: "validDB.WithInvalid.collection"},
localField: "x",
foreignField: "_id.x",
as: "results",
},
},
{
$lookup: {
from: {db: "wrongDB", coll: `${chunksCollName}`},
localField: "x",
foreignField: "_id.x",
as: "results",
},
},
{
$lookup: {
from: {db: "config", coll: "validDB.LetLookup.invalidCollectionName"},
let: {x_field: "$x"},
pipeline: [{$match: {$expr: {$eq: ["$_id.x", "$$x_field"]}}}],
as: "results",
},
},
{
$lookup: {
from: {db: "wrongDBWithLet", coll: `${chunksCollName}`},
let: {x_field: "$x"},
pipeline: [{$match: {$expr: {$eq: ["$_id.x", "$$x_field"]}}}],
as: "results",
},
},
];
invalidLookups.forEach((testCase) => {
assertErrorCode(
sourceCollection,
[testCase],
ErrorCodes.FailedToParse,
`Expected $lookup to fail. Original command: ${tojson(testCase)}`,
);
});
const nodeList = DiscoverTopology.findNonConfigNodes(st.s);
// Tests that $lookup from config.cache.chunks.* yields the expected results.
const testLookupFromConfigCacheChunks = (lookupAgg) => {
jsTestLog(`Running test on lookup: ${tojson(lookupAgg)}`);
const results = sourceCollection.aggregate(lookupAgg).toArray();
results.forEach((res) => {
assert.eq(res.results.length, 1, `Failed with results ${tojson(results)}`);
});
};
setUp();
const lookupBasic = {
$lookup: {
from: {db: "config", coll: `${chunksCollName}`},
localField: "x",
foreignField: "_id.x",
as: "results",
},
};
testLookupFromConfigCacheChunks(lookupBasic);
const lookupLet = {
$lookup: {
from: {db: "config", coll: `${chunksCollName}`},
let: {x_field: "$x"},
pipeline: [{$match: {$expr: {$eq: ["$_id.x", "$$x_field"]}}}],
as: "results",
},
};
testLookupFromConfigCacheChunks(lookupLet);
st.stop();