Files
mongo/jstests/aggregation/text/text_score_metadata.js
Zac 591928c619 SERVER-108478 JS formatted by prettier and remove clang-format (#39656)
GitOrigin-RevId: 6c8f6aded47f260aa4f7c231b17dae3302cb1e04
2025-08-21 17:27:09 +00:00

112 lines
3.6 KiB
JavaScript

/**
* Tests that the "text score" metadata (previously known as 'textScore') is accessible by the
* 'score' metadata field in aggregation pipelines.
*
* @tags: [featureFlagRankFusionFull, requires_fcv_81]
*/
const kScoreMetadataArg = "score";
const kTextScoreMetadataArg = "textScore";
const coll = db.foo;
coll.drop();
assert.commandWorked(
coll.insertMany([
{_id: 0, x: "test"},
{_id: 1, x: "hello"},
{_id: 2, x: "test test"},
]),
);
assert.commandWorked(coll.createIndex({x: "text"}));
const textMatchStage = {
$match: {$text: {$search: "test"}},
};
/**
* Helper function to project $textScore in an aggregation, including the option to force the
* projection on the merging shard.
* @param {boolean} forceProjectionOnMerger force the metadata project to be run on the merging
* shard, otherwise allow it to be pushed down.
*/
function runProjectionTest({forceProjectionOnMerger}) {
function buildPipeline(projections) {
let pipeline = [textMatchStage];
if (forceProjectionOnMerger) {
// Add a splitPipeline stage so that the $project will stay on the merging shard and
// exercise dependency analysis there.
pipeline.push({$_internalSplitPipeline: {}});
}
pipeline.push({$project: projections});
return pipeline;
}
const pipelineWithScoreAndTextScore = buildPipeline({
[kTextScoreMetadataArg]: {$meta: kTextScoreMetadataArg},
[kScoreMetadataArg]: {$meta: kScoreMetadataArg},
});
// Generate a document set with both the 'score' and 'textScore' metadata fields projected as
// regular fields.
let results = coll.aggregate(pipelineWithScoreAndTextScore).toArray();
// Ensure both 'score' and 'textScore' are present and equal.
assert.neq(results.length, 0, "results array expected not to be empty");
for (let result of results) {
assert(
result.hasOwnProperty(kTextScoreMetadataArg),
`Failed to find ${kTextScoreMetadataArg} in document: ${tojson(result)}`,
);
assert(
result.hasOwnProperty(kScoreMetadataArg),
`Failed to find ${kScoreMetadataArg} in document: ${tojson(result)}`,
);
assert.eq(
result[kTextScoreMetadataArg],
result[kScoreMetadataArg],
"the legacy metadata value '" + kTextScoreMetadataArg + "' is not equal to the 'score' metadata value",
);
}
// We should also be able to project $score by itself.
const pipelineWithScoreOnly = buildPipeline({[kScoreMetadataArg]: {$meta: kScoreMetadataArg}});
results = coll.aggregate(pipelineWithScoreOnly).toArray();
assert.neq(results.length, 0, "results array expected not to be empty");
for (let result of results) {
assert(result.hasOwnProperty(kScoreMetadataArg), result);
}
}
(function testProjectScore() {
runProjectionTest({forceProjectionOnMerger: false});
})();
(function testProjectScoreOnMergingShard() {
runProjectionTest({forceProjectionOnMerger: true});
})();
(function testSortOnScore() {
const results = coll
.aggregate([textMatchStage, {$sort: {[kScoreMetadataArg]: {$meta: kScoreMetadataArg}}}])
.toArray();
assert.eq(results, [
{_id: 2, x: "test test"},
{_id: 0, x: "test"},
]);
})();
(function testGroupOnScore() {
// We should have two distinct entries for two different returned scores.
const results = coll
.aggregate([textMatchStage, {$group: {_id: {$meta: kScoreMetadataArg}, count: {$sum: 1}}}])
.toArray();
assert.eq(results.length, 2, results);
})();