summaryrefslogtreecommitdiff
path: root/jstests/core/index/fts/fts_score_sort.js
diff options
context:
space:
mode:
authorGregory Noma <gregory.noma@gmail.com>2023-01-09 21:02:31 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-01-09 22:32:29 +0000
commit4be00f9aef88e082f0ef170873fb5c7e30da1c1c (patch)
tree156a7d7e9ce1e1e8a2c5c5d404a0c4b5127b2434 /jstests/core/index/fts/fts_score_sort.js
parent9c2d2f716db7924c7fe12af379437f637efba744 (diff)
downloadmongo-4be00f9aef88e082f0ef170873fb5c7e30da1c1c.tar.gz
SERVER-64473 Split up `core` jstest directory
Diffstat (limited to 'jstests/core/index/fts/fts_score_sort.js')
-rw-r--r--jstests/core/index/fts/fts_score_sort.js124
1 files changed, 124 insertions, 0 deletions
diff --git a/jstests/core/index/fts/fts_score_sort.js b/jstests/core/index/fts/fts_score_sort.js
new file mode 100644
index 00000000000..b9103ad0c6b
--- /dev/null
+++ b/jstests/core/index/fts/fts_score_sort.js
@@ -0,0 +1,124 @@
+// Test sorting with text score metadata.
+(function() {
+"use strict";
+
+const kUnavailableMetadataErrCode = 40218;
+
+const coll = db.getSiblingDB("test").getCollection("fts_score_sort");
+coll.drop();
+
+assert.commandWorked(coll.insert({_id: 0, a: "textual content"}));
+assert.commandWorked(coll.insert({_id: 1, a: "additional content"}));
+assert.commandWorked(coll.insert({_id: 2, a: "irrelevant content"}));
+assert.commandWorked(coll.createIndex({a: "text"}));
+
+// $meta sort specification should be rejected if it has additional keys.
+assert.throws(function() {
+ coll.find({$text: {$search: "textual content"}}, {score: {$meta: "textScore"}})
+ .sort({score: {$meta: "textScore", extra: 1}})
+ .itcount();
+});
+
+// $meta sort specification should be rejected if the type of meta sort is not known.
+assert.throws(function() {
+ coll.find({$text: {$search: "textual content"}}, {score: {$meta: "textScore"}})
+ .sort({score: {$meta: "unknown"}})
+ .itcount();
+});
+
+// Sort spefication should be rejected if a $-keyword other than $meta is used.
+assert.throws(function() {
+ coll.find({$text: {$search: "textual content"}}, {score: {$meta: "textScore"}})
+ .sort({score: {$notMeta: "textScore"}})
+ .itcount();
+});
+
+// Sort spefication should be rejected if it is a string, not an object with $meta.
+assert.throws(function() {
+ coll.find({$text: {$search: "textual content"}}, {score: {$meta: "textScore"}})
+ .sort({score: "textScore"})
+ .itcount();
+});
+
+// Sort by the text score.
+let results =
+ coll.find({$text: {$search: "textual content -irrelevant"}}, {score: {$meta: "textScore"}})
+ .sort({score: {$meta: "textScore"}})
+ .toArray();
+assert.eq(
+ results,
+ [{_id: 0, a: "textual content", score: 1.5}, {_id: 1, a: "additional content", score: 0.75}]);
+
+// Sort by {_id descending, score} and verify the order is right.
+results =
+ coll.find({$text: {$search: "textual content -irrelevant"}}, {score: {$meta: "textScore"}})
+ .sort({_id: -1, score: {$meta: "textScore"}})
+ .toArray();
+assert.eq(
+ results,
+ [{_id: 1, a: "additional content", score: 0.75}, {_id: 0, a: "textual content", score: 1.5}]);
+
+// Can $meta sort by text score without a meta projection using either find or agg.
+let expectedResults = [{_id: 0, a: "textual content"}, {_id: 1, a: "additional content"}];
+results = coll.find({$text: {$search: "textual content -irrelevant"}})
+ .sort({score: {$meta: "textScore"}})
+ .toArray();
+assert.eq(results, expectedResults);
+results = coll.aggregate([
+ {$match: {$text: {$search: "textual content -irrelevant"}}},
+ {$sort: {score: {$meta: "textScore"}}}
+ ])
+ .toArray();
+assert.eq(results, expectedResults);
+
+// $meta-sort by text score fails if there is no $text predicate, for both find and agg.
+let error = assert.throws(() => coll.find().sort({score: {$meta: "textScore"}}).itcount());
+assert.commandFailedWithCode(error, kUnavailableMetadataErrCode);
+error = assert.throws(() => coll.aggregate([{$sort: {score: {$meta: "textScore"}}}]).itcount());
+assert.commandFailedWithCode(error, kUnavailableMetadataErrCode);
+
+// Test a sort pattern like {<field>: {$meta: "textScore"}} is legal even if <field> is explicitly
+// included by the projection. Test that this is true for both the find and aggregate commands.
+expectedResults = [{a: "textual content"}, {a: "additional content"}];
+results = coll.find({$text: {$search: "textual content -irrelevant"}}, {_id: 0, a: 1})
+ .sort({a: {$meta: "textScore"}})
+ .toArray();
+assert.eq(results, expectedResults);
+results = coll.aggregate([
+ {$match: {$text: {$search: "textual content -irrelevant"}}},
+ {$project: {_id: 0, a: 1}},
+ {$sort: {a: {$meta: "textScore"}}}
+ ])
+ .toArray();
+assert.eq(results, expectedResults);
+
+// Test that both find and agg can $meta-project the textScore with a non-$meta sort on the same
+// field. The semantics of find are that the sort logically occurs before the projection, so we
+// expect the data to be sorted according the values that were present prior to the $meta
+// projection.
+expectedResults = [{_id: 0, a: 0.75}, {_id: 1, a: 1.5}];
+results = coll.find({$text: {$search: "additional content -irrelevant"}},
+ {_id: 1, a: {$meta: "textScore"}})
+ .sort({a: -1})
+ .toArray();
+assert.eq(results, expectedResults);
+results = coll.aggregate([
+ {$match: {$text: {$search: "additional content -irrelevant"}}},
+ {$sort: {a: -1}},
+ {$project: {_id: 1, a: {$meta: "textScore"}}}
+ ])
+ .toArray();
+assert.eq(results, expectedResults);
+
+// Test that an aggregate command with a $project-then-$sort pipeline can sort on the
+// $meta-projected data without repeating the $meta operator in the $sort.
+results = coll.aggregate([
+ {$match: {$text: {$search: "textual content -irrelevant"}}},
+ {$project: {a: 1, score: {$meta: "textScore"}}},
+ {$sort: {score: -1}}
+ ])
+ .toArray();
+assert.eq(
+ results,
+ [{_id: 0, a: "textual content", score: 1.5}, {_id: 1, a: "additional content", score: 0.75}]);
+}());