summaryrefslogtreecommitdiff
path: root/jstests/core
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
commit4cb8841196d0625dfa3825aa326f071cd27c7b8b (patch)
tree1682a647d4463397c119183369ae6f750d5fdcff /jstests/core
parentaa03c6362cbaa767638e6eed9b031d86dd2643d1 (diff)
parent8f0827553e09872941945a093b647a4211a9db7f (diff)
Update upstream source from tag 'upstream/6.0.0'master
Update to upstream version '6.0.0' with Debian dir 5604a80ec1c96ca76f25f40d78e6ef855abec322
Diffstat (limited to 'jstests/core')
-rw-r--r--jstests/core/aggregation_accepts_write_concern.js6
-rw-r--r--jstests/core/api_version_new_50_language_features.js48
-rw-r--r--jstests/core/api_version_new_51_language_features.js3
-rw-r--r--jstests/core/api_version_new_52_language_features.js16
-rw-r--r--jstests/core/api_version_test_expression.js1
-rw-r--r--jstests/core/arrayfind8.js1
-rw-r--r--jstests/core/awaitdata_getmore_cmd.js5
-rw-r--r--jstests/core/bittest.js7
-rw-r--r--jstests/core/bypass_doc_validation.js1
-rw-r--r--jstests/core/bypass_empty_ts_replacement.js202
-rw-r--r--jstests/core/bypass_empty_ts_replacement_timeseries.js73
-rw-r--r--jstests/core/capped_large_docs.js4
-rw-r--r--jstests/core/check_shard_index.js107
-rw-r--r--jstests/core/clustered_collection_collation.js51
-rw-r--r--jstests/core/collation.js314
-rw-r--r--jstests/core/collection_uuid_coll_mod.js13
-rw-r--r--jstests/core/collection_uuid_drop.js13
-rw-r--r--jstests/core/collection_uuid_find.js14
-rw-r--r--jstests/core/collection_uuid_index_commands.js18
-rw-r--r--jstests/core/collection_uuid_rename_collection.js17
-rw-r--r--jstests/core/collection_uuid_write_commands.js14
-rw-r--r--jstests/core/collmod.js14
-rw-r--r--jstests/core/collmod_convert_index_uniqueness.js9
-rw-r--r--jstests/core/collmod_convert_to_ttl.js7
-rw-r--r--jstests/core/collmod_convert_to_unique_apply_ops.js7
-rw-r--r--jstests/core/collmod_convert_to_unique_violations.js10
-rw-r--r--jstests/core/command_let_variables.js155
-rw-r--r--jstests/core/command_let_variables_expressions.js208
-rw-r--r--jstests/core/commands_namespace_parsing.js1
-rw-r--r--jstests/core/compact_keeps_indexes.js1
-rw-r--r--jstests/core/connection_string_validation.js1
-rw-r--r--jstests/core/cover_null_queries.js338
-rw-r--r--jstests/core/create_indexes.js6
-rw-r--r--jstests/core/currentop_cursors.js1
-rw-r--r--jstests/core/currentop_shell.js2
-rw-r--r--jstests/core/currentop_waiting_for_latch.js3
-rw-r--r--jstests/core/doc_validation_with_now_variable.js20
-rw-r--r--jstests/core/elemmatch_or_pushdown_paths.js74
-rw-r--r--jstests/core/empty_ts.js134
-rw-r--r--jstests/core/exhaust.js1
-rw-r--r--jstests/core/explain5.js2
-rw-r--r--jstests/core/explain_agg_write_concern.js1
-rw-r--r--jstests/core/explain_skip.js28
-rw-r--r--jstests/core/expr_index_use.js5
-rw-r--r--jstests/core/field_name_validation.js10
-rw-r--r--jstests/core/find_with_resume_after_param.js105
-rw-r--r--jstests/core/fts_index.js11
-rw-r--r--jstests/core/fts_index3.js11
-rw-r--r--jstests/core/fts_mix.js1
-rw-r--r--jstests/core/group_lookup_with_canonical_query_prefix.js130
-rw-r--r--jstests/core/hostinfo.js4
-rw-r--r--jstests/core/index/sparse_index_internal_expr.js71
-rw-r--r--jstests/core/index_elemmatch1.js39
-rw-r--r--jstests/core/index_elemmatch2.js (renamed from jstests/core/elemmatch_index.js)54
-rw-r--r--jstests/core/index_filter_commands.js3
-rw-r--r--jstests/core/index_partial_create_drop.js4
-rw-r--r--jstests/core/index_partial_read_ops.js5
-rw-r--r--jstests/core/index_prepareUnique.js16
-rw-r--r--jstests/core/index_stats.js13
-rw-r--r--jstests/core/json_schema/json_schema.js2
-rw-r--r--jstests/core/json_schema/misc_validation.js1
-rw-r--r--jstests/core/latch_analyzer.js2
-rw-r--r--jstests/core/list_collections_name_only.js2
-rw-r--r--jstests/core/map_reduce_subplanning.js47
-rw-r--r--jstests/core/match_with_and_or_lockstep_enumeration.js110
-rw-r--r--jstests/core/monotonic_date_operations.js408
-rw-r--r--jstests/core/mr_single_reduce.js22
-rw-r--r--jstests/core/nested_or_duplicate_predicates_index_scan.js51
-rw-r--r--jstests/core/no_db_created.js4
-rw-r--r--jstests/core/notablescan.js61
-rw-r--r--jstests/core/null_query_semantics.js164
-rw-r--r--jstests/core/opcounters_write_cmd.js1
-rw-r--r--jstests/core/operation_latency_histogram.js1
-rw-r--r--jstests/core/or_to_in.js133
-rw-r--r--jstests/core/partialFilterExpression_with_geoWithin.js9
-rw-r--r--jstests/core/partial_index_logical.js177
-rw-r--r--jstests/core/plan_cache_list_plans.js1
-rw-r--r--jstests/core/plan_cache_stats_shard_and_host.js31
-rw-r--r--jstests/core/profile_agg.js1
-rw-r--r--jstests/core/profile_update.js27
-rw-r--r--jstests/core/project_with_collation.js185
-rw-r--r--jstests/core/query/internal_strip_invalid_assignment.js45
-rw-r--r--jstests/core/rename_collection_system_db.js7
-rw-r--r--jstests/core/rename_collection_view.js86
-rw-r--r--jstests/core/shell_connection_strings.js1
-rw-r--r--jstests/core/timeseries/bucket_unpacking_with_sort.js3
-rw-r--r--jstests/core/timeseries/bucket_unpacking_with_sort_extended_range.js269
-rw-r--r--jstests/core/timeseries/bucket_unpacking_with_sort_plan_cache.js2
-rw-r--r--jstests/core/timeseries/libs/timeseries.js33
-rw-r--r--jstests/core/timeseries/nondefault_collation.js325
-rw-r--r--jstests/core/timeseries/partialFilterExpression_with_internalBucketGeoWithin.js7
-rw-r--r--jstests/core/timeseries/timeseries_bucket_rename.js28
-rw-r--r--jstests/core/timeseries/timeseries_collection_uuid.js42
-rw-r--r--jstests/core/timeseries/timeseries_collmod.js13
-rw-r--r--jstests/core/timeseries/timeseries_computed_field.js856
-rw-r--r--jstests/core/timeseries/timeseries_create_collection.js9
-rw-r--r--jstests/core/timeseries/timeseries_delete_hint.js6
-rw-r--r--jstests/core/timeseries/timeseries_field_parsed_as_bson.js70
-rw-r--r--jstests/core/timeseries/timeseries_filter_extended_range.js185
-rw-r--r--jstests/core/timeseries/timeseries_geonear_lookup.js40
-rw-r--r--jstests/core/timeseries/timeseries_geonear_measurements.js4
-rw-r--r--jstests/core/timeseries/timeseries_graph_lookup.js1
-rw-r--r--jstests/core/timeseries/timeseries_groupby_reorder.js233
-rw-r--r--jstests/core/timeseries/timeseries_index.js9
-rw-r--r--jstests/core/timeseries/timeseries_index_partial.js33
-rw-r--r--jstests/core/timeseries/timeseries_index_spec.js5
-rw-r--r--jstests/core/timeseries/timeseries_index_use.js25
-rw-r--r--jstests/core/timeseries/timeseries_insert_mixed_schema_bucket.js75
-rw-r--r--jstests/core/timeseries/timeseries_internal_bucket_geo_within.js6
-rw-r--r--jstests/core/timeseries/timeseries_lastpoint_top.js1
-rw-r--r--jstests/core/timeseries/timeseries_lookup.js299
-rw-r--r--jstests/core/timeseries/timeseries_match_pushdown.js634
-rw-r--r--jstests/core/timeseries/timeseries_match_pushdown_with_project.js131
-rw-r--r--jstests/core/timeseries/timeseries_merge.js1
-rw-r--r--jstests/core/timeseries/timeseries_metric_index_2dsphere.js3
-rw-r--r--jstests/core/timeseries/timeseries_metric_index_ascending_descending.js3
-rw-r--r--jstests/core/timeseries/timeseries_metric_index_compound.js3
-rw-r--r--jstests/core/timeseries/timeseries_predicates.js204
-rw-r--r--jstests/core/timeseries/timeseries_project.js185
-rw-r--r--jstests/core/timeseries/timeseries_project_pushdown.js196
-rw-r--r--jstests/core/timeseries/timeseries_resume_after.js21
-rw-r--r--jstests/core/timeseries/timeseries_sparse_index.js3
-rw-r--r--jstests/core/timeseries/timeseries_streaming_group.js159
-rw-r--r--jstests/core/timeseries/timeseries_union_with.js5
-rw-r--r--jstests/core/timeseries/timeseries_update_mixed_schema_bucket.js79
-rw-r--r--jstests/core/transaction_too_large_for_cache.js56
-rw-r--r--jstests/core/ttl_index_options.js14
-rw-r--r--jstests/core/txns/abort_expired_transaction.js13
-rw-r--r--jstests/core/txns/aggregation_in_transaction.js2
-rw-r--r--jstests/core/txns/out_not_blocked_by_txn.js44
-rw-r--r--jstests/core/txns/prepare_conflict_aggregation_behavior.js7
-rw-r--r--jstests/core/txns/transaction_too_large_for_cache.js85
-rw-r--r--jstests/core/views/invalid_system_views.js2
-rw-r--r--jstests/core/views/views_aggregation.js1
-rw-r--r--jstests/core/views/views_all_commands.js12
-rw-r--r--jstests/core/views/views_collation.js1
-rw-r--r--jstests/core/views/views_creation.js1
-rw-r--r--jstests/core/views/views_validation.js1
-rw-r--r--jstests/core/wildcard_index_validindex.js17
139 files changed, 826 insertions, 7648 deletions
diff --git a/jstests/core/aggregation_accepts_write_concern.js b/jstests/core/aggregation_accepts_write_concern.js
index 8117c296e03..2c764414a1d 100644
--- a/jstests/core/aggregation_accepts_write_concern.js
+++ b/jstests/core/aggregation_accepts_write_concern.js
@@ -1,11 +1,7 @@
/**
* Confirms that the aggregate command accepts writeConcern regardless of whether the pipeline
* writes or is read-only.
- * @tags: [
- * assumes_write_concern_unchanged,
- * does_not_support_stepdowns,
- * references_foreign_collection
- * ]
+ * @tags: [assumes_write_concern_unchanged, does_not_support_stepdowns]
*/
(function() {
"use strict";
diff --git a/jstests/core/api_version_new_50_language_features.js b/jstests/core/api_version_new_50_language_features.js
index 8d73124b2eb..71ea01d53f2 100644
--- a/jstests/core/api_version_new_50_language_features.js
+++ b/jstests/core/api_version_new_50_language_features.js
@@ -12,7 +12,6 @@
load("jstests/libs/api_version_helpers.js"); // For 'APIVersionHelpers'.
const collName = "api_version_new_50_language_features";
-const viewName = collName + "_view";
const coll = db[collName];
coll.drop();
assert.commandWorked(coll.insert({a: 1, date: new ISODate()}));
@@ -26,12 +25,53 @@ const stablePipelines = [
[{$set: {x: {$setField: {input: "$$ROOT", field: "x", value: "foo"}}}}],
];
+function assertAggregateFailsWithAPIStrict(pipeline, errorCodes) {
+ assert.commandFailedWithCode(db.runCommand({
+ aggregate: collName,
+ pipeline: pipeline,
+ cursor: {},
+ apiStrict: true,
+ apiVersion: "1"
+ }),
+ errorCodes,
+ pipeline);
+}
+
+function assertAggregateSucceedsWithAPIStrict(pipeline) {
+ assert.commandWorked(db.runCommand(
+ {aggregate: collName, pipeline: pipeline, cursor: {}, apiStrict: true, apiVersion: "1"}));
+}
+
+function assertViewFailsWithAPIStrict(pipeline) {
+ assert.commandFailedWithCode(db.runCommand({
+ create: 'new_50_feature_view',
+ viewOn: collName,
+ pipeline: pipeline,
+ apiStrict: true,
+ apiVersion: "1"
+ }),
+ ErrorCodes.APIStrictError,
+ pipeline);
+}
+
+function assertViewSucceedsWithAPIStrict(pipeline) {
+ assert.commandWorked(db.runCommand({
+ create: 'new_50_feature_view',
+ viewOn: collName,
+ pipeline: pipeline,
+ apiStrict: true,
+ apiVersion: "1"
+ }));
+
+ assert.commandWorked(db.runCommand({drop: 'new_50_feature_view'}));
+}
+
for (let pipeline of stablePipelines) {
// Assert error thrown when running a pipeline with stages not in API Version 1.
APIVersionHelpers.assertAggregateSucceedsWithAPIStrict(pipeline, collName);
// Assert error thrown when creating a view on a pipeline with stages not in API Version 1.
- APIVersionHelpers.assertViewSucceedsWithAPIStrict(pipeline, viewName, collName);
+ assertViewSucceedsWithAPIStrict(pipeline);
// Assert error is not thrown when running without apiStrict=true.
assert.commandWorked(db.runCommand({
@@ -50,14 +90,14 @@ const setWindowFieldsPipeline = [{
output: {runningCount: {$sum: 1, window: {documents: ["unbounded", "current"]}}}
}
}];
-APIVersionHelpers.assertAggregateSucceedsWithAPIStrict(setWindowFieldsPipeline, collName);
+assertAggregateSucceedsWithAPIStrict(setWindowFieldsPipeline);
APIVersionHelpers.assertAggregateSucceedsWithAPIStrict(
setWindowFieldsPipeline,
collName,
[ErrorCodes.InvalidOptions, ErrorCodes.OperationNotSupportedInTransaction]);
-APIVersionHelpers.assertViewSucceedsWithAPIStrict(setWindowFieldsPipeline, viewName, collName);
+APIVersionHelpers.assertViewSucceedsWithAPIStrict(setWindowFieldsPipeline, collName);
// Creating a collection with dotted paths is allowed with apiStrict:true.
diff --git a/jstests/core/api_version_new_51_language_features.js b/jstests/core/api_version_new_51_language_features.js
index 48e73d7e052..5d923e3bd2f 100644
--- a/jstests/core/api_version_new_51_language_features.js
+++ b/jstests/core/api_version_new_51_language_features.js
@@ -12,7 +12,6 @@
load("jstests/libs/api_version_helpers.js"); // For 'APIVersionHelpers'.
const collName = "api_version_new_51_language_features";
-const viewName = collName + "_view";
const coll = db[collName];
coll.drop();
assert.commandWorked(coll.insert({a: 1, date: new ISODate()}));
@@ -27,7 +26,7 @@ for (let pipeline of stablePipelines) {
APIVersionHelpers.assertAggregateSucceedsWithAPIStrict(pipeline, collName);
// Assert error thrown when creating a view on a pipeline with stages not in API Version 1.
- APIVersionHelpers.assertViewSucceedsWithAPIStrict(pipeline, viewName, collName);
+ APIVersionHelpers.assertViewSucceedsWithAPIStrict(pipeline, collName);
// Assert error is not thrown when running without apiStrict=true.
assert.commandWorked(db.runCommand({
diff --git a/jstests/core/api_version_new_52_language_features.js b/jstests/core/api_version_new_52_language_features.js
index e50f2f96160..3fc21934853 100644
--- a/jstests/core/api_version_new_52_language_features.js
+++ b/jstests/core/api_version_new_52_language_features.js
@@ -11,21 +11,7 @@
"use strict";
load("jstests/libs/api_version_helpers.js"); // For 'APIVersionHelpers'.
-function isFeatureFlagEnabled(featureFlag) {
- const featureFlagParam = db.adminCommand({getParameter: 1, [featureFlag]: 1});
- return featureFlagParam.hasOwnProperty(featureFlag) && featureFlagParam[featureFlag]["value"];
-}
-
-// Since parallel test suite ignores feature flags in some scenarios we need explicitly check if the
-// required flag is enabled.
-if (!isFeatureFlagEnabled('featureFlagExactTopNAccumulator')) {
- jsTestLog(
- "Skipping the test because required feature flag 'featureFlagExactTopNAccumulator' is disabled");
- return;
-}
-
const collName = "api_version_new_52_language_features";
-const viewName = collName + "_view";
const coll = db[collName];
coll.drop();
assert.commandWorked(coll.insert({a: 1, arr: [2, 1, 4]}));
@@ -97,7 +83,7 @@ for (const pipeline of stablePipelines) {
APIVersionHelpers.assertAggregateSucceedsWithAPIStrict(pipeline, collName);
// Assert creating a view on a pipeline with stages in API Version 1 succeeds.
- APIVersionHelpers.assertViewSucceedsWithAPIStrict(pipeline, viewName, collName);
+ APIVersionHelpers.assertViewSucceedsWithAPIStrict(pipeline, collName);
// Assert error is not thrown when running without apiStrict=true.
assert.commandWorked(db.runCommand({
diff --git a/jstests/core/api_version_test_expression.js b/jstests/core/api_version_test_expression.js
index 3252ebda83e..41bbd9c0402 100644
--- a/jstests/core/api_version_test_expression.js
+++ b/jstests/core/api_version_test_expression.js
@@ -8,7 +8,6 @@
* assumes_unsharded_collection,
* uses_api_parameters,
* no_selinux,
- * references_foreign_collection,
* ]
*/
diff --git a/jstests/core/arrayfind8.js b/jstests/core/arrayfind8.js
index ee74aae33ef..87a3a8d701a 100644
--- a/jstests/core/arrayfind8.js
+++ b/jstests/core/arrayfind8.js
@@ -81,6 +81,7 @@ function checkQuery(subQuery, bothMatch, elemMatch, nonElemMatch, additionalCons
insertValueIfNotNull(bothMatch);
insertValueIfNotNull(elemMatch);
insertValueIfNotNull(nonElemMatch);
+
checkMatch(bothMatch, elemMatch, nonElemMatch, standardQuery, elemMatchQuery, 'unindexed');
// Check matching and index bounds for a single key index.
diff --git a/jstests/core/awaitdata_getmore_cmd.js b/jstests/core/awaitdata_getmore_cmd.js
index f2c766ca29b..8ad2634d27e 100644
--- a/jstests/core/awaitdata_getmore_cmd.js
+++ b/jstests/core/awaitdata_getmore_cmd.js
@@ -171,7 +171,7 @@ const topology = DiscoverTopology.findConnectedNodes(db.getMongo());
if (topology.type !== Topology.kStandalone) {
const readConcern =
assert.commandWorked(db.adminCommand({getDefaultRWConcern: 1})).defaultReadConcern;
- if (readConcern.level == "majority" || TestData.defaultReadConcernLevel === "majority") {
+ if (readConcern.level == "majority") {
return;
}
}
@@ -214,8 +214,7 @@ assert.soon(() => db.await_data.findOne({_id: "signal parent shell"}) !== null);
// Now issue a getMore which will match the parallel shell's currentOp filter, signalling it to
// write a non-matching document into the collection. Confirm that we do not receive this
// document and that we subsequently time out.
-cmdRes = db.runCommand(
- {getMore: cmdRes.cursor.id, collection: collName, maxTimeMS: ReplSetTest.kDefaultTimeoutMS});
+cmdRes = db.runCommand({getMore: cmdRes.cursor.id, collection: collName, maxTimeMS: 4000});
assert.commandWorked(cmdRes);
jsTestLog("Waiting insertion shell to terminate...");
assert.eq(insertshell(), 0);
diff --git a/jstests/core/bittest.js b/jstests/core/bittest.js
index a0d81b64eef..a4a7272ae28 100644
--- a/jstests/core/bittest.js
+++ b/jstests/core/bittest.js
@@ -169,13 +169,6 @@ assert.commandWorked(coll.insert({a: 1.1}));
assert.commandWorked(coll.insert({a: -1.1}));
assert.commandWorked(coll.insert({a: -Infinity}));
assert.commandWorked(coll.insert({a: +Infinity}));
-assert.commandWorked(coll.insert({a: NumberDecimal("Infinity")}));
-assert.commandWorked(coll.insert({a: NumberDecimal("-Infinity")}));
-assert.commandWorked(coll.insert({a: NumberDecimal("NaN")}));
-assert.commandWorked(coll.insert({a: NumberDecimal(Number.MAX_SAFE_LONG + 1)}));
-assert.commandWorked(coll.insert({a: NumberDecimal(Number.MIN_SAFE_LONG - 1)}));
-assert.commandWorked(coll.insert({a: NumberDecimal(1.1)}));
-assert.commandWorked(coll.insert({a: NumberDecimal(-1.1)}));
assert.commandWorked(coll.createIndex({a: 1}));
assertQueryCorrect({a: {$bitsAllSet: 0}}, 5);
diff --git a/jstests/core/bypass_doc_validation.js b/jstests/core/bypass_doc_validation.js
index 1fd32db658b..d290508835a 100644
--- a/jstests/core/bypass_doc_validation.js
+++ b/jstests/core/bypass_doc_validation.js
@@ -6,7 +6,6 @@
// uses_map_reduce_with_temp_collections,
// # Tenant migrations don't support applyOps.
// tenant_migration_incompatible,
-// references_foreign_collection,
// ]
/**
diff --git a/jstests/core/bypass_empty_ts_replacement.js b/jstests/core/bypass_empty_ts_replacement.js
deleted file mode 100644
index 9bd74f3f0ca..00000000000
--- a/jstests/core/bypass_empty_ts_replacement.js
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * Tests the "bypassEmptyTsReplacement" option.
- *
- * @tags: [
- * requires_fcv_60,
- * ]
- */
-(function() {
-"use strict";
-
-const coll = db.jstests_bypass_empty_ts_replacement;
-const collName = coll.getName();
-const emptyTs = Timestamp(0, 0);
-
-coll.drop();
-
-function doInsert(docs, bypassEmptyTsReplacement) {
- let cmdRes = db.runCommand(
- {insert: collName, documents: docs, bypassEmptyTsReplacement: bypassEmptyTsReplacement});
- assert.commandWorked(cmdRes);
-}
-
-function doUpdate(filter, update, bypassEmptyTsReplacement) {
- let cmdRes = db.runCommand({
- update: collName,
- updates: [{q: filter, u: update}],
- bypassEmptyTsReplacement: bypassEmptyTsReplacement
- });
- assert.commandWorked(cmdRes);
-}
-
-function doUpdateWithUpsert(filter, update, bypassEmptyTsReplacement) {
- let cmdRes = db.runCommand({
- update: collName,
- updates: [{q: filter, u: update, upsert: true}],
- bypassEmptyTsReplacement: bypassEmptyTsReplacement
- });
- assert.commandWorked(cmdRes);
-}
-
-function doFindAndModify(filter, update, bypassEmptyTsReplacement) {
- let cmdRes = db.runCommand({
- findAndModify: collName,
- query: filter,
- update: update,
- bypassEmptyTsReplacement: bypassEmptyTsReplacement
- });
- assert.commandWorked(cmdRes);
-}
-
-function doFindAndModifyWithUpsert(filter, update, bypassEmptyTsReplacement) {
- let cmdRes = db.runCommand({
- findAndModify: collName,
- query: filter,
- update: update,
- upsert: true,
- bypassEmptyTsReplacement: bypassEmptyTsReplacement
- });
- assert.commandWorked(cmdRes);
-}
-
-let numCallsToRunTests = 0;
-
-function runTests(bypassEmptyTsReplacement) {
- ++numCallsToRunTests;
-
- let first = (numCallsToRunTests == 1);
- let startId = numCallsToRunTests * 100;
-
- function getId(i) {
- return startId + i;
- }
-
- // The insert/update/findAndModify commands below will be run with the bypassEmptyTsReplacement
- // parameter set to true or false (depending whether the 'bypassEmptyTsReplacement' variable is
- // true or false).
-
- // Insert several documents.
- doInsert([{_id: getId(1), a: emptyTs}], bypassEmptyTsReplacement);
- doInsert([{_id: getId(2), a: 1}], bypassEmptyTsReplacement);
- doInsert([{_id: getId(3), a: 2}], bypassEmptyTsReplacement);
- doInsert([{_id: getId(6), a: 3}], bypassEmptyTsReplacement);
- doInsert([{_id: getId(7), a: 4}], bypassEmptyTsReplacement);
- doInsert([{_id: getId(8), a: 5}], bypassEmptyTsReplacement);
- doInsert([{_id: getId(9), a: 6}], bypassEmptyTsReplacement);
- doInsert([{_id: getId(10), a: 7}], bypassEmptyTsReplacement);
- doInsert([{_id: getId(11), a: 8}], bypassEmptyTsReplacement);
-
- // Use a replacement-style update to update the doc with _id=getId(2).
- //
- // When bypassEmptyTsReplacement=true, this is an example of how the special "empty timestamp"
- // behavior can be suppressed when doing a replacement-style update.
- doUpdate({_id: getId(2)}, {a: emptyTs}, bypassEmptyTsReplacement);
-
- // Use a replacement-style findAndModify to update the doc with _id=getId(3).
- doFindAndModify({_id: getId(3)}, {a: emptyTs}, bypassEmptyTsReplacement);
-
- // Do a replacement-style update to add a new document with _id=getId(4).
- doUpdateWithUpsert({_id: getId(4)}, {a: emptyTs}, bypassEmptyTsReplacement);
-
- // Do a replacement-style findAndModify to add a new document with _id=getId(5).
- doFindAndModifyWithUpsert({_id: getId(5)}, {a: emptyTs}, bypassEmptyTsReplacement);
-
- // Do an update-operator-style update to update the doc with _id=getId(6).
- doUpdate({_id: getId(6)}, {$set: {a: emptyTs}}, bypassEmptyTsReplacement);
-
- // Do an update-operator-style findAndModify to update the doc with _id=getId(7).
- doFindAndModify({_id: getId(7)}, {$set: {a: emptyTs}}, bypassEmptyTsReplacement);
-
- // Do a pipeline-style update to update the doc with _id=getId(8).
- doUpdate({_id: getId(8)}, [{$addFields: {a: emptyTs}}], bypassEmptyTsReplacement);
-
- // Do a pipeline-style findAndModify to update the doc with _id=getId(9).
- doFindAndModify({_id: getId(9)}, [{$addFields: {a: emptyTs}}], bypassEmptyTsReplacement);
-
- // Do a pipeline-style update with $internalApplyOplogUpdate to update the doc with
- // _id=getId(10).
- doUpdate({_id: getId(10)},
- [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}],
- bypassEmptyTsReplacement);
-
- // Do a pipeline-style findAndModify with $internalApplyOplogUpdate to update the doc with
- // _id=getId(11).
- doFindAndModify({_id: getId(11)},
- [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}],
- bypassEmptyTsReplacement);
-
- // Do an update-operator-style update to add a new document with _id=getId(12).
- doUpdateWithUpsert({_id: getId(12)}, {$set: {a: emptyTs}}, bypassEmptyTsReplacement);
-
- // Do an update-operator-style findAndModify to add a new document with _id=getId(13).
- doFindAndModifyWithUpsert({_id: getId(13)}, {$set: {a: emptyTs}}, bypassEmptyTsReplacement);
-
- // Do a pipeline-style update to add a new document with _id=getId(14).
- doUpdateWithUpsert({_id: getId(14)}, [{$addFields: {a: emptyTs}}], bypassEmptyTsReplacement);
-
- // Do a pipeline-style findAndModify to add a new document with _id=getId(15).
- doFindAndModifyWithUpsert(
- {_id: getId(15)}, [{$addFields: {a: emptyTs}}], bypassEmptyTsReplacement);
-
- // Do a pipline-style update with $internalApplyOplogUpdate to add a new document with
- // _id=getId(16).
- doUpdateWithUpsert(
- {_id: getId(16)},
- [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}],
- bypassEmptyTsReplacement);
-
- // Do pipeline-style findAndModify with $internalApplyOplogUpdate to add a new document
- // with _id=getId(17).
- doFindAndModifyWithUpsert(
- {_id: getId(17)},
- [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}],
- bypassEmptyTsReplacement);
-
- // Verify that all the insert, update, and findAndModify commands behaved the way we expected.
- // If 'bypassEmptyTsReplacement' is true, then we expect field "a" will be equal to the empty
- // timestamp for all 17 documents. If 'bypassEmptyTsReplacement' is false, then we expect
- // field "a" will be equal to the current timestamp for the first 5 documents and it will
- // be equal to the empty timestamp for the other 12 documents.
- for (let i = 1; i <= 17; ++i) {
- let result = coll.findOne({_id: getId(i)});
-
- if (bypassEmptyTsReplacement || i >= 6) {
- assert.eq(tojson(result.a), tojson(emptyTs), "_id=" + getId(i));
- } else {
- assert.neq(tojson(result.a), tojson(emptyTs), "_id=" + getId(i));
- }
- }
-
- if (first) {
- // If this is the first time that runTests() is invoked, insert a document with
- // _id=Timestamp(0,0), and then verify that the document we just inserted can be
- // retrieved using the filter "{_id: Timestamp(0,0)}".
- doInsert([{_id: emptyTs, a: 9}], bypassEmptyTsReplacement);
-
- let result = coll.findOne({_id: emptyTs});
- assert.eq(tojson(result._id), tojson(emptyTs), "_id=" + tojson(emptyTs));
- assert.eq(tojson(result.a), tojson(9), "_id=" + tojson(emptyTs));
- }
-
- // Do a replacement-style update on the document with _id=Timestamp(0,0).
- doUpdate({_id: emptyTs}, {_id: emptyTs, a: emptyTs}, bypassEmptyTsReplacement);
-
- // Verify the document we just updated can still be retrieved using "{_id: Timestamp(0,0)}".
- let result = coll.findOne({_id: emptyTs});
- assert.eq(tojson(result._id), tojson(emptyTs), "_id=" + tojson(emptyTs));
-
- if (bypassEmptyTsReplacement) {
- // Verify that an empty timestamp value was stored in field "a".
- assert.eq(tojson(result.a), tojson(emptyTs), "_id=" + tojson(emptyTs));
- } else {
- // Verify that field "a" was set to the current timestamp.
- assert.neq(tojson(result.a), tojson(emptyTs), "_id=" + tojson(emptyTs));
- }
-}
-
-let bypassEmptyTsReplacement = true;
-runTests(bypassEmptyTsReplacement);
-
-bypassEmptyTsReplacement = false;
-runTests(bypassEmptyTsReplacement);
-}());
diff --git a/jstests/core/bypass_empty_ts_replacement_timeseries.js b/jstests/core/bypass_empty_ts_replacement_timeseries.js
deleted file mode 100644
index 69a5bcf281c..00000000000
--- a/jstests/core/bypass_empty_ts_replacement_timeseries.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * Tests inserts, updates, and upserts on a timeseries collection with "bypassEmptyTsReplacement"
- * set to true.
- *
- * @tags: [
- * assumes_no_implicit_collection_creation_after_drop,
- * does_not_support_transactions,
- * requires_fcv_60,
- * requires_multi_updates,
- * requires_non_retryable_writes,
- * requires_timeseries,
- * ]
- */
-(function() {
-"use strict";
-
-const coll = db.jstests_bypass_empty_ts_replacement_timeseries;
-const collName = coll.getName();
-const emptyTs = Timestamp(0, 0);
-
-coll.drop();
-
-assert.commandWorked(db.createCollection(collName, {timeseries: {timeField: "t", metaField: "m"}}));
-
-function doInsert(docs, bypassEmptyTsReplacement) {
- let cmdRes = db.runCommand(
- {insert: collName, documents: docs, bypassEmptyTsReplacement: bypassEmptyTsReplacement});
- assert.commandWorked(cmdRes);
-}
-
-function doUpdate(filter, update, bypassEmptyTsReplacement) {
- let cmdRes = db.runCommand({
- update: collName,
- updates: [{q: filter, u: update, multi: true}],
- bypassEmptyTsReplacement: bypassEmptyTsReplacement
- });
- assert.commandWorked(cmdRes);
-}
-
-let numCallsToRunTests = 0;
-
-function runTests(bypassEmptyTsReplacement) {
- ++numCallsToRunTests;
-
- let startId = numCallsToRunTests * 100;
-
- function getId(i) {
- return startId + i;
- }
-
- // Insert two documents.
- doInsert([{_id: getId(1), t: new Date(100), m: emptyTs, a: emptyTs}], bypassEmptyTsReplacement);
- doInsert([{_id: getId(2), t: new Date(200), m: getId(2), a: emptyTs}],
- bypassEmptyTsReplacement);
-
- // Do a replacement-style update containing an empty timestamp value.
- doUpdate({m: getId(2)}, {$set: {m: emptyTs}}, bypassEmptyTsReplacement);
-
- // Verify that the commands above didn't mutate any of the empty timestamp values in the
- // collection.
- for (let i = 1; i <= 2; ++i) {
- let result = coll.findOne({_id: getId(i)});
- assert.eq(tojson(result.m), tojson(emptyTs), "_id=" + getId(i));
- assert.eq(tojson(result.a), tojson(emptyTs), "_id=" + getId(i));
- }
-}
-
-let bypassEmptyTsReplacement = true;
-runTests(bypassEmptyTsReplacement);
-
-bypassEmptyTsReplacement = false;
-runTests(bypassEmptyTsReplacement);
-}());
diff --git a/jstests/core/capped_large_docs.js b/jstests/core/capped_large_docs.js
index 310562fbb6c..f32a3e33389 100644
--- a/jstests/core/capped_large_docs.js
+++ b/jstests/core/capped_large_docs.js
@@ -2,10 +2,6 @@
* Tests inserting large documents into a capped collection.
*
* @tags: [
- * # Suites with stepdowns will result in replication rollback, and we do not update tracked
- * # collection size for replication rollback. Thus if this occurs during the inserts, we can
- * # end up with fewer documents in the capped collection than we would otherwise expect.
- * does_not_support_stepdowns,
* requires_capped,
* requires_collstats,
* requires_fastcount,
diff --git a/jstests/core/check_shard_index.js b/jstests/core/check_shard_index.js
index 23f69c6b757..61e84c038b1 100644
--- a/jstests/core/check_shard_index.js
+++ b/jstests/core/check_shard_index.js
@@ -21,12 +21,12 @@ f.createIndex({x: 1, y: 1});
assert.eq(0, f.count(), "1. initial count should be zero");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandWorked(res, "1a " + tojson(res));
+assert.eq(true, res.ok, "1a");
f.save({x: 1, y: 1});
assert.eq(1, f.count(), "1. count after initial insert should be 1");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandWorked(res, "1b " + tojson(res));
+assert.eq(true, res.ok, "1b");
// -------------------------
// Case 2: entry with null values would make an index suitable
@@ -40,16 +40,16 @@ f.save({x: 1, y: 1});
f.save({x: null, y: 1});
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandWorked(res, "2a " + tojson(res));
+assert.eq(true, res.ok, "2a " + tojson(res));
f.save({y: 2});
assert.eq(3, f.count(), "2. count after initial insert should be 3");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandWorked(res, "2b " + tojson(res));
+assert.eq(true, res.ok, "2b " + tojson(res));
// Check _id index
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {_id: 1}});
-assert.commandWorked(res, "2c " + tojson(res));
+assert.eq(true, res.ok, "2c " + tojson(res));
assert(res.idskip, "2d " + tojson(res));
// -------------------------
@@ -65,7 +65,7 @@ f.save({x: [1, 2], y: 2});
assert.eq(2, f.count(), "3. count after initial insert should be 2");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res, "3a " + tojson(res));
+assert.eq(false, res.ok, "3a " + tojson(res));
f.remove({y: 2});
f.dropIndex({x: 1, y: 1});
@@ -73,13 +73,13 @@ f.createIndex({x: 1, y: 1});
assert.eq(1, f.count(), "3. count after removing array value should be 1");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandWorked(res, "3b " + tojson(res));
+assert.eq(true, res.ok, "3b " + tojson(res));
f.save({x: 2, y: [1, 2]});
assert.eq(2, f.count(), "3. count after adding array value should be 2");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res, "3c " + tojson(res));
+assert.eq(false, res.ok, "3c " + tojson(res));
// -------------------------
// Case 4: Handles prefix shard key indexes.
@@ -93,21 +93,21 @@ f.save({x: 1, y: 1, z: 1});
assert.eq(1, f.count(), "4. count after initial insert should be 1");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1}});
-assert.commandWorked(res, "4a " + tojson(res));
+assert.eq(true, res.ok, "4a " + tojson(res));
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandWorked(res, "4b " + tojson(res));
+assert.eq(true, res.ok, "4b " + tojson(res));
f.save({x: [1, 2], y: 2, z: 2});
assert.eq(2, f.count(), "4. count after adding array value should be 2");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1}});
-assert.commandFailed(res, "4c " + tojson(res));
+assert.eq(false, res.ok, "4c " + tojson(res));
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res, "4d " + tojson(res));
+assert.eq(false, res.ok, "4d " + tojson(res));
res = db.runCommand(
{checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1, z: 1}});
-assert.commandFailed(res, "4e " + tojson(res));
+assert.eq(false, res.ok, "4e " + tojson(res));
f.remove({y: 2});
f.dropIndex({x: 1, y: 1, z: 1});
@@ -116,18 +116,18 @@ f.createIndex({x: 1, y: 1, z: 1});
assert.eq(1, f.count(), "4. count after removing array value should be 1");
res = db.runCommand(
{checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1, z: 1}});
-assert.commandWorked(res, "4f " + tojson(res));
+assert.eq(true, res.ok, "4f " + tojson(res));
f.save({x: 3, y: [1, 2], z: 3});
assert.eq(2, f.count(), "4. count after adding array value on second key should be 2");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1}});
-assert.commandFailed(res, "4g " + tojson(res));
+assert.eq(false, res.ok, "4g " + tojson(res));
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res, "4h " + tojson(res));
+assert.eq(false, res.ok, "4h " + tojson(res));
res = db.runCommand(
{checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1, z: 1}});
-assert.commandFailed(res, "4i " + tojson(res));
+assert.eq(false, res.ok, "4i " + tojson(res));
f.remove({x: 3});
// Necessary so that the index is no longer marked as multikey
@@ -137,82 +137,17 @@ f.createIndex({x: 1, y: 1, z: 1});
assert.eq(1, f.count(), "4. count after removing array value should be 1 again");
res = db.runCommand(
{checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1, z: 1}});
-assert.commandWorked(res, "4e " + tojson(res));
+assert.eq(true, res.ok, "4e " + tojson(res));
f.save({x: 4, y: 4, z: [1, 2]});
assert.eq(2, f.count(), "4. count after adding array value on third key should be 2");
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1}});
-assert.commandFailed(res, "4c " + tojson(res));
+assert.eq(false, res.ok, "4c " + tojson(res));
res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res, "4d " + tojson(res));
+assert.eq(false, res.ok, "4d " + tojson(res));
res = db.runCommand(
{checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1, z: 1}});
-assert.commandFailed(res, "4e " + tojson(res));
-
-// -------------------------
-// Test error messages of checkShardingIndex failing:
-
-// Shard key is not a prefix of index key:
-f.drop();
-f.createIndex({x: 1});
-res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {y: 1}});
-assert.commandFailed(res);
-assert(res.errmsg.includes("Shard key is not a prefix of index key."));
-
-// Index key is partial:
-f.drop();
-f.createIndex({x: 1, y: 1}, {partialFilterExpression: {y: {$gt: 0}}});
-res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res);
-assert(res.errmsg.includes("Index key is partial."));
-
-// Index key is sparse:
-f.drop();
-f.createIndex({x: 1, y: 1}, {sparse: true});
-res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res);
-assert(res.errmsg.includes("Index key is sparse."));
-
-// Index key is multikey:
-f.drop();
-f.createIndex({x: 1, y: 1});
-f.save({y: [1, 2, 3, 4, 5]});
-res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res);
-assert(res.errmsg.includes("Index key is multikey."));
-
-// Index key has a non-simple collation:
-f.drop();
-f.createIndex({x: 1, y: 1}, {collation: {locale: "en"}});
-res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res);
-assert(res.errmsg.includes("Index has a non-simple collation."));
-
-// Index key is sparse and index has non-simple collation:
-f.drop();
-f.createIndex({x: 1, y: 1}, {sparse: true, collation: {locale: "en"}});
-res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res);
-assert(res.errmsg.includes("Index key is sparse.") &&
- res.errmsg.includes("Index has a non-simple collation."));
-
-// Multiple incompatible indexes: Index key is multikey and is partial:
-f.drop();
-f.createIndex({x: 1, y: 1}, {name: "index_1_part", partialFilterExpression: {x: {$gt: 0}}});
-f.createIndex({x: 1, y: 1}, {name: "index_2"});
-f.save({y: [1, 2, 3, 4, 5]});
-res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res);
-assert(res.errmsg.includes("Index key is multikey.") &&
- res.errmsg.includes("Index key is partial."));
-
-// Multiple incompatible indexes: Index key is partial and sparse:
-f.drop();
-f.createIndex({x: 1, y: 1}, {name: "index_1_part", partialFilterExpression: {x: {$gt: 0}}});
-f.createIndex({x: 1, y: 1}, {name: "index_2_sparse", sparse: true});
-res = db.runCommand({checkShardingIndex: "test.jstests_shardingindex", keyPattern: {x: 1, y: 1}});
-assert.commandFailed(res);
-assert(res.errmsg.includes("Index key is partial.") && res.errmsg.includes("Index key is sparse."));
+assert.eq(false, res.ok, "4e " + tojson(res));
print("PASSED");
diff --git a/jstests/core/clustered_collection_collation.js b/jstests/core/clustered_collection_collation.js
index 585425d6fac..d96afb7730d 100644
--- a/jstests/core/clustered_collection_collation.js
+++ b/jstests/core/clustered_collection_collation.js
@@ -35,9 +35,6 @@ const incompatibleCollation = {
locale: "fr_CA",
strength: 2
};
-const simpleCollation = {
- locale: "simple",
-};
assert.commandWorked(db.createCollection(
collatedName, {clusteredIndex: {key: {_id: 1}, unique: true}, collation: defaultCollation}));
@@ -144,7 +141,7 @@ const verifyNoTightBoundsAndFindsN = function(coll, expected, predicate, queryCo
const max = res.queryPlanner.winningPlan.maxRecord;
assert.neq(null, min, "No min bound");
assert.neq(null, max, "No max bound");
- assert(min !== max, "COLLSCAN bounds are equal");
+ assert.neq(min, max, "COLLSCAN bounds are equal");
assert.eq(expected, coll.find(predicate).count(), "Didn't find the expected records");
};
@@ -153,77 +150,33 @@ const testBounds = function(coll, expected, defaultCollation) {
verifyHasBoundsAndFindsN(coll, 1, {_id: 5});
verifyHasBoundsAndFindsN(coll, 1, {_id: {int: 5}});
verifyHasBoundsAndFindsN(coll, 1, {_id: {ints: [5, 10]}});
- verifyNoTightBoundsAndFindsN(coll, 2, {_id: {$in: [5, {ints: [5, 10]}]}});
// Test non string types with incompatible collations.
verifyHasBoundsAndFindsN(coll, 1, {_id: 5}, incompatibleCollation);
verifyHasBoundsAndFindsN(coll, 1, {_id: {int: 5}}, incompatibleCollation);
verifyHasBoundsAndFindsN(coll, 1, {_id: {ints: [5, 10]}}, incompatibleCollation);
- verifyNoTightBoundsAndFindsN(
- coll, 2, {_id: {$in: [5, {ints: [5, 10]}]}}, incompatibleCollation);
// Test strings respect the collation.
verifyHasBoundsAndFindsN(coll, expected, {_id: "A"});
verifyHasBoundsAndFindsN(coll, expected, {_id: {str: "A"}});
verifyHasBoundsAndFindsN(coll, expected, {_id: {strs: ["A", "b"]}});
verifyHasBoundsAndFindsN(coll, expected, {_id: {strs: ["a", "B"]}});
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["A", 1]}});
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["A", "C"]}});
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["", {str: "A"}]}});
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: [{}, {strs: ["A", "b"]}]}});
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: [[], {strs: ["a", "B"]}]}});
// Test strings not in the _id field
verifyNoBoundsAndFindsN(coll, expected, {data: ["A", "b"]});
verifyNoBoundsAndFindsN(coll, expected, {data: ["a", "B"]});
- // Test non compatible query collations don't generate exact bounds. This means, the bounds
- // generated are with respect to the KeyString encoding of the data type of the query. For
- // example, an _id: <string> query will be bounded by min and max values for type 'string', but
- // not bounded by the exact value of <string>.
+ // Test non compatible query collations don't generate bounds
verifyNoTightBoundsAndFindsN(coll, expected, {_id: "A"}, incompatibleCollation);
verifyNoTightBoundsAndFindsN(coll, expected, {_id: {str: "A"}}, incompatibleCollation);
verifyNoTightBoundsAndFindsN(coll, expected, {_id: {strs: ["A", "b"]}}, incompatibleCollation);
verifyNoTightBoundsAndFindsN(coll, expected, {_id: {strs: ["a", "B"]}}, incompatibleCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["A", 1]}}, incompatibleCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["A", "C"]}}, incompatibleCollation);
- verifyNoTightBoundsAndFindsN(
- coll, expected, {_id: {$in: ["", {str: "A"}]}}, incompatibleCollation);
- verifyNoTightBoundsAndFindsN(
- coll, expected, {_id: {$in: [{}, {strs: ["A", "b"]}]}}, incompatibleCollation);
- verifyNoTightBoundsAndFindsN(
- coll, expected, {_id: {$in: [[], {strs: ["a", "B"]}]}}, incompatibleCollation);
-
- if (defaultCollation != undefined && defaultCollation.locale != simpleCollation.locale) {
- // 'Simple' collations are treated differently than non-simple queries since they are the
- // default 'locale' when a collation is not specified. Test that the 'simple' collation is
- // not compatible when the clustered collection has a non-simple collation.
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: "A"}, simpleCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {str: "A"}}, simpleCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {strs: ["A", "b"]}}, simpleCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {strs: ["a", "B"]}}, simpleCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["A", 1]}}, simpleCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["A", "C"]}}, simpleCollation);
- verifyNoTightBoundsAndFindsN(
- coll, expected, {_id: {$in: ["", {str: "A"}]}}, simpleCollation);
- verifyNoTightBoundsAndFindsN(
- coll, expected, {_id: {$in: [{}, {strs: ["A", "b"]}]}}, simpleCollation);
- verifyNoTightBoundsAndFindsN(
- coll, expected, {_id: {$in: [[], {strs: ["a", "B"]}]}}, simpleCollation);
- }
// Test compatible query collations generate bounds
verifyHasBoundsAndFindsN(coll, expected, {_id: "A"}, defaultCollation);
verifyHasBoundsAndFindsN(coll, expected, {_id: {str: "A"}}, defaultCollation);
verifyHasBoundsAndFindsN(coll, expected, {_id: {strs: ["A", "b"]}}, defaultCollation);
verifyHasBoundsAndFindsN(coll, expected, {_id: {strs: ["a", "B"]}}, defaultCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["A", 1]}}, defaultCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["A", "C"]}}, defaultCollation);
- verifyNoTightBoundsAndFindsN(coll, expected, {_id: {$in: ["", {str: "A"}]}}, defaultCollation);
- verifyNoTightBoundsAndFindsN(
- coll, expected, {_id: {$in: [{}, {strs: ["A", "b"]}]}}, defaultCollation);
- verifyNoTightBoundsAndFindsN(
- coll, expected, {_id: {$in: [[], {strs: ["a", "B"]}]}}, defaultCollation);
};
insertDocuments(collated);
diff --git a/jstests/core/collation.js b/jstests/core/collation.js
index 558d1af428c..6a7ff93c9c7 100644
--- a/jstests/core/collation.js
+++ b/jstests/core/collation.js
@@ -24,19 +24,18 @@ load("jstests/libs/sbe_explain_helpers.js"); // For engineSpecificAssertion.
// For areAllCollectionsClustered.
load("jstests/libs/clustered_collections/clustered_collection_util.js");
-let testDb = db.getSiblingDB("collation_js");
-var coll = testDb.collation;
+var coll = db.collation;
coll.drop();
var explainRes;
var writeRes;
var planStage;
-var hello = testDb.runCommand("hello");
+var hello = db.runCommand("hello");
assert.commandWorked(hello);
var isMongos = (hello.msg === "isdbgrid");
var isStandalone = !isMongos && !hello.hasOwnProperty('setName');
-var isClustered = ClusteredCollectionUtil.areAllCollectionsClustered(testDb);
+var isClustered = ClusteredCollectionUtil.areAllCollectionsClustered(db);
var assertIndexHasCollation = function(keyPattern, collation) {
var indexSpecs = coll.getIndexes();
@@ -62,38 +61,35 @@ var getQueryCollation = function(explainRes) {
};
//
-// Test using testDb.createCollection() to make a collection with a default collation.
+// Test using db.createCollection() to make a collection with a default collation.
//
// Attempting to create a collection with an invalid collation should fail.
-assert.commandFailed(testDb.createCollection("collation", {collation: "not an object"}));
-assert.commandFailed(testDb.createCollection("collation", {collation: {}}));
-assert.commandFailed(testDb.createCollection("collation", {collation: {blah: 1}}));
-assert.commandFailed(testDb.createCollection("collation", {collation: {locale: "en", blah: 1}}));
-assert.commandFailed(testDb.createCollection("collation", {collation: {locale: "xx"}}));
-assert.commandFailed(
- testDb.createCollection("collation", {collation: {locale: "en", strength: 99}}));
-assert.commandFailed(
- testDb.createCollection("collation", {collation: {locale: "en", strength: 9.9}}));
+assert.commandFailed(db.createCollection("collation", {collation: "not an object"}));
+assert.commandFailed(db.createCollection("collation", {collation: {}}));
+assert.commandFailed(db.createCollection("collation", {collation: {blah: 1}}));
+assert.commandFailed(db.createCollection("collation", {collation: {locale: "en", blah: 1}}));
+assert.commandFailed(db.createCollection("collation", {collation: {locale: "xx"}}));
+assert.commandFailed(db.createCollection("collation", {collation: {locale: "en", strength: 99}}));
+assert.commandFailed(db.createCollection("collation", {collation: {locale: "en", strength: 9.9}}));
// Attempting to create a collection whose collation version does not match the collator version
// produced by ICU should result in failure with a special error code.
assert.commandFailedWithCode(
- testDb.createCollection("collation", {collation: {locale: "en", version: "unknownVersion"}}),
+ db.createCollection("collation", {collation: {locale: "en", version: "unknownVersion"}}),
ErrorCodes.IncompatibleCollationVersion);
// Ensure we can create a collection with the "simple" collation as the collection default.
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "simple"}}));
-var collectionInfos = testDb.getCollectionInfos({name: coll.getName()});
+assert.commandWorked(db.createCollection("collation", {collation: {locale: "simple"}}));
+var collectionInfos = db.getCollectionInfos({name: "collation"});
assert.eq(collectionInfos.length, 1);
assert(!collectionInfos[0].options.hasOwnProperty("collation"));
+coll.drop();
// Ensure that we populate all collation-related fields when we create a collection with a valid
// collation.
-coll = testDb.collation_frCA;
-coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
-var collectionInfos = testDb.getCollectionInfos({name: coll.getName()});
+assert.commandWorked(db.createCollection("collation", {collation: {locale: "fr_CA"}}));
+var collectionInfos = db.getCollectionInfos({name: "collation"});
assert.eq(collectionInfos.length, 1);
assert.eq(collectionInfos[0].options.collation, {
locale: "fr_CA",
@@ -180,8 +176,8 @@ if (isStandalone) {
assertIndexHasCollation({c: 1}, {locale: "simple"});
}
-coll = testDb.collation_index1;
coll.drop();
+
//
// Creating an index with a collation.
//
@@ -259,7 +255,6 @@ assertIndexHasCollation({e: 1}, {locale: "simple"});
// Test that an index with a non-simple collation contains collator-generated comparison keys
// rather than the verbatim indexed strings.
-coll = testDb.collation_index2;
coll.drop();
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "fr_CA"}}));
assert.commandWorked(coll.createIndex({b: 1}));
@@ -271,41 +266,37 @@ assert.eq("foo", coll.find().collation({locale: "fr_CA"}).hint({b: 1}).returnKey
// Test that a query with a string comparison can use an index with a non-simple collation if it
// has a matching collation.
-coll = testDb.collation_index3;
coll.drop();
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "fr_CA"}}));
// Query has simple collation, but index has fr_CA collation.
explainRes = coll.find({a: "foo"}).explain();
assert.commandWorked(explainRes);
-assert(planHasStage(testDb, getWinningPlan(explainRes.queryPlanner), "COLLSCAN"));
+assert(planHasStage(db, getWinningPlan(explainRes.queryPlanner), "COLLSCAN"));
// Query has en_US collation, but index has fr_CA collation.
explainRes = coll.find({a: "foo"}).collation({locale: "en_US"}).explain();
assert.commandWorked(explainRes);
-assert(planHasStage(testDb, getWinningPlan(explainRes.queryPlanner), "COLLSCAN"));
+assert(planHasStage(db, getWinningPlan(explainRes.queryPlanner), "COLLSCAN"));
// Matching collations.
explainRes = coll.find({a: "foo"}).collation({locale: "fr_CA"}).explain();
assert.commandWorked(explainRes);
-assert(planHasStage(testDb, getWinningPlan(explainRes.queryPlanner), "IXSCAN"));
+assert(planHasStage(db, getWinningPlan(explainRes.queryPlanner), "IXSCAN"));
// Should not be possible to create a text index with an explicit non-simple collation.
-coll = testDb.collation_index3;
coll.drop();
assert.commandFailed(coll.createIndex({a: "text"}, {collation: {locale: "en"}}));
// Text index builds which inherit a non-simple default collation should fail.
-coll = testDb.collation_en1;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en"}}));
assert.commandFailed(coll.createIndex({a: "text"}));
// Text index build should succeed on a collection with a non-simple default collation if it
// explicitly overrides the default with {locale: "simple"}.
-coll = testDb.collation_en2;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en"}}));
assert.commandWorked(coll.createIndex({a: "text"}, {collation: {locale: "simple"}}));
//
@@ -314,12 +305,10 @@ assert.commandWorked(coll.createIndex({a: "text"}, {collation: {locale: "simple"
// Aggregation should return correct results when collation specified and collection does not
// exist.
-coll = testDb.collation_agg1;
coll.drop();
assert.eq(0, coll.aggregate([], {collation: {locale: "fr"}}).itcount());
// Aggregation should return correct results when collation specified and collection does exist.
-coll = testDb.collation_agg2;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "bar"}));
@@ -330,39 +319,35 @@ assert.eq(1,
// Aggregation should return correct results when no collation specified and collection has a
// default collation.
-coll = testDb.collation_agg3;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({str: "foo"}));
assert.eq(1, coll.aggregate([{$match: {str: "FOO"}}]).itcount());
// Aggregation should return correct results when "simple" collation specified and collection
// has a default collation.
-coll = testDb.collation_agg4;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({str: "foo"}));
assert.eq(0, coll.aggregate([{$match: {str: "FOO"}}], {collation: {locale: "simple"}}).itcount());
// Aggregation should select compatible index when no collation specified and collection has a
// default collation.
-coll = testDb.collation_agg5;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "en_US"}}));
var explain = coll.explain("queryPlanner").aggregate([{$match: {a: "foo"}}]);
-assert(isIxscan(testDb, getWinningPlan(explain.queryPlanner)));
+assert(isIxscan(db, getWinningPlan(explain.queryPlanner)));
// Aggregation should not use index when no collation specified and collection default
// collation is incompatible with index collation.
-coll = testDb.collation_agg6;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "simple"}}));
var explain = coll.explain("queryPlanner").aggregate([{$match: {a: "foo"}}]);
-assert(isCollscan(testDb, getWinningPlan(explain.queryPlanner)));
+assert(isCollscan(db, getWinningPlan(explain.queryPlanner)));
// Explain of aggregation with collation should succeed.
assert.commandWorked(coll.explain().aggregate([], {collation: {locale: "fr"}}));
@@ -372,12 +357,10 @@ assert.commandWorked(coll.explain().aggregate([], {collation: {locale: "fr"}}));
//
// Count should return correct results when collation specified and collection does not exist.
-coll = testDb.collation_count1;
coll.drop();
assert.eq(0, coll.find({str: "FOO"}).collation({locale: "en_US"}).count());
// Count should return correct results when collation specified and collection does exist.
-coll = testDb.collation_count1;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "bar"}));
@@ -390,24 +373,21 @@ assert.eq(1, coll.count({str: "FOO"}, {collation: {locale: "en_US", strength: 2}
// Count should return correct results when no collation specified and collection has a default
// collation.
-coll = testDb.collation_count3;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({str: "foo"}));
assert.eq(1, coll.find({str: "FOO"}).count());
// Count should return correct results when "simple" collation specified and collection has a
// default collation.
-coll = testDb.collation_count4;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({str: "foo"}));
assert.eq(0, coll.find({str: "FOO"}).collation({locale: "simple"}).count());
// Count should return correct results when collation specified and when run with explain.
-coll = testDb.collation_count5;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "bar"}));
@@ -426,7 +406,6 @@ assert.neq(null, planStage);
assert.eq(1, planStage.advanced);
// Explain of COUNT_SCAN stage should include index collation.
-coll = testDb.collation_count6;
coll.drop();
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "fr_CA"}}));
explainRes = coll.explain("executionStats").find({a: 5}).count();
@@ -448,9 +427,8 @@ assert.eq(planStage.collation, {
// Explain of COUNT_SCAN stage should include index collation when index collation is
// inherited from collection default.
-coll = testDb.collation_count7;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
assert.commandWorked(coll.createIndex({a: 1}));
explainRes = coll.explain("executionStats").find({a: 5}).count();
assert.commandWorked(explainRes);
@@ -470,14 +448,13 @@ assert.eq(planStage.collation, {
});
// Should be able to use COUNT_SCAN for queries over strings.
-coll = testDb.collation_count8;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
assert.commandWorked(coll.createIndex({a: 1}));
explainRes = coll.explain("executionStats").find({a: "foo"}).count();
assert.commandWorked(explainRes);
-assert(planHasStage(testDb, explainRes.executionStats.executionStages, "COUNT_SCAN"));
-assert(!planHasStage(testDb, explainRes.executionStats.executionStages, "FETCH"));
+assert(planHasStage(db, explainRes.executionStats.executionStages, "COUNT_SCAN"));
+assert(!planHasStage(db, explainRes.executionStats.executionStages, "FETCH"));
//
// Collation tests for distinct.
@@ -485,12 +462,10 @@ assert(!planHasStage(testDb, explainRes.executionStats.executionStages, "FETCH")
// Distinct should return correct results when collation specified and collection does not
// exist.
-coll = testDb.collation_distinct1;
coll.drop();
assert.eq(0, coll.distinct("str", {}, {collation: {locale: "en_US", strength: 2}}).length);
// Distinct should return correct results when collation specified and no indexes exist.
-coll = testDb.collation_distinct2;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "FOO"}));
@@ -510,10 +485,9 @@ assert.eq(2, coll.distinct("str", {}, {collation: {locale: "en_US", strength: 3}
// Distinct should return correct results when no collation specified and collection has a
// default collation.
-coll = testDb.collation_distinct3;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({str: "foo"}));
assert.commandWorked(coll.insert({str: "FOO"}));
assert.eq(1, coll.distinct("str").length);
@@ -521,10 +495,9 @@ assert.eq(2, coll.distinct("_id", {str: "foo"}).length);
// Distinct should return correct results when "simple" collation specified and collection has a
// default collation.
-coll = testDb.collation_distinct4;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({str: "foo"}));
assert.commandWorked(coll.insert({str: "FOO"}));
assert.eq(2, coll.distinct("str", {}, {collation: {locale: "simple"}}).length);
@@ -532,45 +505,42 @@ assert.eq(1, coll.distinct("_id", {str: "foo"}, {collation: {locale: "simple"}})
// Distinct should select compatible index when no collation specified and collection has a
// default collation.
-coll = testDb.collation_distinct5;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "en_US"}}));
var explain = coll.explain("queryPlanner").distinct("a");
-assert(planHasStage(testDb, getWinningPlan(explain.queryPlanner), "DISTINCT_SCAN"));
-assert(planHasStage(testDb, getWinningPlan(explain.queryPlanner), "FETCH"));
+assert(planHasStage(db, getWinningPlan(explain.queryPlanner), "DISTINCT_SCAN"));
+assert(planHasStage(db, getWinningPlan(explain.queryPlanner), "FETCH"));
// Distinct scan on strings can be used over an index with a collation when the predicate has
// exact bounds.
explain = coll.explain("queryPlanner").distinct("a", {a: {$gt: "foo"}});
-assert(planHasStage(testDb, getWinningPlan(explain.queryPlanner), "DISTINCT_SCAN"));
-assert(planHasStage(testDb, getWinningPlan(explain.queryPlanner), "FETCH"));
-assert(!planHasStage(testDb, getWinningPlan(explain.queryPlanner), "PROJECTION_COVERED"));
+assert(planHasStage(db, getWinningPlan(explain.queryPlanner), "DISTINCT_SCAN"));
+assert(planHasStage(db, getWinningPlan(explain.queryPlanner), "FETCH"));
+assert(!planHasStage(db, getWinningPlan(explain.queryPlanner), "PROJECTION_COVERED"));
// Distinct scan cannot be used over an index with a collation when the predicate has inexact
// bounds.
explain = coll.explain("queryPlanner").distinct("a", {a: {$exists: true}});
-assert(planHasStage(testDb, getWinningPlan(explain.queryPlanner), "IXSCAN"));
-assert(planHasStage(testDb, getWinningPlan(explain.queryPlanner), "FETCH"));
-assert(!planHasStage(testDb, getWinningPlan(explain.queryPlanner), "DISTINCT_SCAN"));
+assert(planHasStage(db, getWinningPlan(explain.queryPlanner), "IXSCAN"));
+assert(planHasStage(db, getWinningPlan(explain.queryPlanner), "FETCH"));
+assert(!planHasStage(db, getWinningPlan(explain.queryPlanner), "DISTINCT_SCAN"));
// Distinct scan can be used without a fetch when predicate has exact non-string bounds.
explain = coll.explain("queryPlanner").distinct("a", {a: {$gt: 3}});
-assert(planHasStage(testDb, getWinningPlan(explain.queryPlanner), "DISTINCT_SCAN"));
-assert(planHasStage(testDb, getWinningPlan(explain.queryPlanner), "PROJECTION_COVERED"));
-assert(!planHasStage(testDb, getWinningPlan(explain.queryPlanner), "FETCH"));
+assert(planHasStage(db, getWinningPlan(explain.queryPlanner), "DISTINCT_SCAN"));
+assert(planHasStage(db, getWinningPlan(explain.queryPlanner), "PROJECTION_COVERED"));
+assert(!planHasStage(db, getWinningPlan(explain.queryPlanner), "FETCH"));
// Distinct should not use index when no collation specified and collection default collation is
// incompatible with index collation.
-coll = testDb.collation_distinct6;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "simple"}}));
var explain = coll.explain("queryPlanner").distinct("a");
-assert(isCollscan(testDb, getWinningPlan(explain.queryPlanner)));
+assert(isCollscan(db, getWinningPlan(explain.queryPlanner)));
// Explain of DISTINCT_SCAN stage should include index collation.
-coll = testDb.collation_distinct7;
coll.drop();
assert.commandWorked(coll.createIndex({str: 1}, {collation: {locale: "fr_CA"}}));
explainRes = coll.explain("executionStats").distinct("str", {}, {collation: {locale: "fr_CA"}});
@@ -592,9 +562,8 @@ assert.eq(planStage.collation, {
// Explain of DISTINCT_SCAN stage should include index collation when index collation is
// inherited from collection default.
-coll = testDb.collation_distinct8;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
assert.commandWorked(coll.createIndex({str: 1}));
explainRes = coll.explain("executionStats").distinct("str");
assert.commandWorked(explainRes);
@@ -619,12 +588,10 @@ assert.eq(planStage.collation, {
// Find should return correct results when collation specified and collection does not
// exist.
-coll = testDb.collation_find1;
coll.drop();
assert.eq(0, coll.find({_id: "FOO"}).collation({locale: "en_US"}).itcount());
// Find should return correct results when collation specified and filter is a match on _id.
-coll = testDb.collation_find2;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "bar"}));
@@ -668,7 +635,6 @@ assert.commandWorked(coll.dropIndexes());
// Queries that use a index with a non-matching collation should add a sort
// stage if needed.
-coll = testDb.collation_find3;
coll.drop();
assert.commandWorked(coll.insert([{a: "A"}, {a: "B"}, {a: "b"}, {a: "a"}]));
@@ -681,7 +647,6 @@ res = coll.find({a: {'$exists': true}}, {_id: 0}).collation({locale: "en_US", st
assert.eq(res.toArray(), [{a: "a"}, {a: "A"}, {a: "b"}, {a: "B"}]);
// Find should return correct results when collation specified and query contains $expr.
-coll = testDb.collation_find4;
coll.drop();
assert.commandWorked(coll.insert([{a: "A"}, {a: "B"}]));
assert.eq(
@@ -689,10 +654,9 @@ assert.eq(
// Find should return correct results when no collation specified and collection has a default
// collation.
-coll = testDb.collation_find5;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({str: "foo"}));
assert.commandWorked(coll.insert({str: "FOO"}));
assert.commandWorked(coll.insert({str: "bar"}));
@@ -704,28 +668,25 @@ assert.eq([{str: "bar"}, {str: "foo"}, {str: "FOO"}],
// Find with idhack should return correct results when no collation specified and collection has
// a default collation.
-coll = testDb.collation_find6;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: "foo"}));
assert.eq(1, coll.find({_id: "FOO"}).itcount());
// Find should return correct results for query containing $expr when no collation specified and
// collection has a default collation.
-coll = testDb.collation_find7;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert([{a: "A"}, {a: "B"}]));
assert.eq(1, coll.find({$expr: {$eq: ["$a", "a"]}}).itcount());
// Find should return correct results when "simple" collation specified and collection has a
// default collation.
-coll = testDb.collation_find8;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({str: "foo"}));
assert.commandWorked(coll.insert({str: "FOO"}));
assert.commandWorked(coll.insert({str: "bar"}));
@@ -736,30 +697,27 @@ assert.eq([{str: "FOO"}, {str: "bar"}, {str: "foo"}],
// Find on _id should return correct results when query collation differs from collection
// default collation.
-coll = testDb.collation_find9;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 3}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 3}}));
assert.commandWorked(coll.insert({_id: "foo"}));
assert.commandWorked(coll.insert({_id: "FOO"}));
assert.eq(2, coll.find({_id: "foo"}).collation({locale: "en_US", strength: 2}).itcount());
if (!isClustered) {
// Find on _id should use idhack stage when query inherits collection default collation.
- coll = testDb.collation_find10;
coll.drop();
- assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+ assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
explainRes = coll.explain("executionStats").find({_id: "foo"}).finish();
assert.commandWorked(explainRes);
let classicAssert = null !== getPlanStage(getWinningPlan(explainRes.queryPlanner), "IDHACK");
let sbeAssert = null !== getPlanStage(getWinningPlan(explainRes.queryPlanner), "IXSCAN");
- engineSpecificAssertion(classicAssert, sbeAssert, testDb, explainRes);
+ engineSpecificAssertion(classicAssert, sbeAssert, db, explainRes);
// Find on _id should use idhack stage when explicitly given query collation matches
// collection default.
- coll = testDb.collation_find11;
coll.drop();
- assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+ assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
explainRes =
coll.explain("executionStats").find({_id: "foo"}).collation({locale: "en_US"}).finish();
assert.commandWorked(explainRes);
@@ -769,9 +727,8 @@ if (!isClustered) {
// Find on _id should not use idhack stage when query collation does not match collection
// default.
- coll = testDb.collation_find12;
coll.drop();
- assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+ assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
explainRes =
coll.explain("executionStats").find({_id: "foo"}).collation({locale: "fr_CA"}).finish();
assert.commandWorked(explainRes);
@@ -783,42 +740,37 @@ if (!isClustered) {
// Find should select compatible index when no collation specified and collection has a default
// collation.
-coll = testDb.collation_find13;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "en_US"}}));
var explain = coll.find({a: "foo"}).explain("queryPlanner");
-assert(isIxscan(testDb, getWinningPlan(explain.queryPlanner)));
+assert(isIxscan(db, getWinningPlan(explain.queryPlanner)));
// Find should select compatible index when no collation specified and collection default
// collation is "simple".
-coll = testDb.collation_find14;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "simple"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "simple"}}));
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "simple"}}));
var explain = coll.find({a: "foo"}).explain("queryPlanner");
-assert(isIxscan(testDb, getWinningPlan(explain.queryPlanner)));
+assert(isIxscan(db, getWinningPlan(explain.queryPlanner)));
// Find should not use index when no collation specified, index collation is "simple", and
// collection has a non-"simple" default collation.
-coll = testDb.collation_find15;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "simple"}}));
var explain = coll.find({a: "foo"}).explain("queryPlanner");
-assert(isCollscan(testDb, getWinningPlan(explain.queryPlanner)));
+assert(isCollscan(db, getWinningPlan(explain.queryPlanner)));
// Find should select compatible index when "simple" collation specified and collection has a
// non-"simple" default collation.
-coll = testDb.collation_find16;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "simple"}}));
var explain = coll.find({a: "foo"}).collation({locale: "simple"}).explain("queryPlanner");
-assert(isIxscan(testDb, getWinningPlan(explain.queryPlanner)));
+assert(isIxscan(db, getWinningPlan(explain.queryPlanner)));
// Find should return correct results when collation specified and run with explain.
-coll = testDb.collation_find17;
coll.drop();
assert.commandWorked(coll.insert({str: "foo"}));
explainRes =
@@ -833,7 +785,6 @@ assert.commandWorked(explainRes);
assert.eq(1, explainRes.executionStats.nReturned);
// Explain of find should include query collation.
-coll = testDb.collation_find18;
coll.drop();
explainRes =
coll.explain("executionStats").find({str: "foo"}).collation({locale: "fr_CA"}).finish();
@@ -852,9 +803,8 @@ assert.eq(getQueryCollation(explainRes), {
});
// Explain of find should include query collation when inherited from collection default.
-coll = testDb.collation_find19;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
explainRes = coll.explain("executionStats").find({str: "foo"}).finish();
assert.commandWorked(explainRes);
assert.eq(getQueryCollation(explainRes), {
@@ -871,7 +821,6 @@ assert.eq(getQueryCollation(explainRes), {
});
// Explain of IXSCAN stage should include index collation.
-coll = testDb.collation_find20;
coll.drop();
assert.commandWorked(coll.createIndex({str: 1}, {collation: {locale: "fr_CA"}}));
explainRes =
@@ -894,9 +843,8 @@ assert.eq(planStage.collation, {
// Explain of IXSCAN stage should include index collation when index collation is inherited from
// collection default.
-coll = testDb.collation_find21;
coll.drop();
-assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
+assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "fr_CA"}}));
assert.commandWorked(coll.createIndex({str: 1}));
explainRes = coll.explain("executionStats").find({str: "foo"}).finish();
assert.commandWorked(explainRes);
@@ -921,7 +869,6 @@ assert.eq(planStage.collation, {
// findAndModify should return correct results when collation specified and collection does not
// exist.
-coll = testDb.collation_findmodify1;
coll.drop();
assert.eq(
null,
@@ -929,7 +876,6 @@ assert.eq(
{query: {str: "bar"}, update: {$set: {str: "baz"}}, new: true, collation: {locale: "fr"}}));
// Update-findAndModify should return correct results when collation specified.
-coll = testDb.collation_findmodify2;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "bar"}));
@@ -953,7 +899,6 @@ assert.neq(null, planStage);
assert.eq(1, planStage.nWouldModify);
// Delete-findAndModify should return correct results when collation specified.
-coll = testDb.collation_findmodify3;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "bar"}));
@@ -974,10 +919,9 @@ assert.eq(1, planStage.nWouldDelete);
// findAndModify should return correct results when no collation specified and collection has a
// default collation.
-coll = testDb.collation_findmodify4;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.eq({_id: 1, str: "foo"}, coll.findAndModify({query: {str: "FOO"}, update: {$set: {x: 1}}}));
@@ -998,10 +942,9 @@ assert.eq({_id: 1, str: "foo", x: 4}, coll.findAndModify({query: {str: "FOO"}, r
// findAndModify should return correct results when "simple" collation specified and collection
// has a default collation.
-coll = testDb.collation_findmodify5;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.eq(null,
coll.findAndModify(
@@ -1014,7 +957,6 @@ assert.eq(null,
//
// mapReduce should return correct results when collation specified and no indexes exist.
-coll = testDb.collation_mapreduce1;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "bar"}));
@@ -1031,10 +973,9 @@ assert.eq(mapReduceOut.results.length, 1);
// mapReduce should return correct results when no collation specified and collection has a
// default collation.
-coll = testDb.collation_mapreduce2;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
var mapReduceOut = coll.mapReduce(
function() {
@@ -1049,10 +990,9 @@ assert.eq(mapReduceOut.results.length, 1);
// mapReduce should return correct results when "simple" collation specified and collection has
// a default collation.
-coll = testDb.collation_mapreduce3;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
var mapReduceOut = coll.mapReduce(
function() {
@@ -1070,12 +1010,10 @@ assert.eq(mapReduceOut.results.length, 0);
//
// Remove should succeed when collation specified and collection does not exist.
-coll = testDb.collation_remove1;
coll.drop();
assert.commandWorked(coll.remove({str: "foo"}, {justOne: true, collation: {locale: "fr"}}));
// Remove should return correct results when collation specified.
-coll = testDb.collation_remove2;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1084,7 +1022,6 @@ assert.commandWorked(writeRes);
assert.eq(1, writeRes.nRemoved);
// Explain of remove should return correct results when collation specified.
-coll = testDb.collation_remove3;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1097,10 +1034,9 @@ assert.eq(1, planStage.nWouldDelete);
// Remove should return correct results when no collation specified and collection has a default
// collation.
-coll = testDb.collation_remove4;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
writeRes = coll.remove({str: "FOO"}, {justOne: true});
assert.commandWorked(writeRes);
@@ -1108,10 +1044,9 @@ assert.eq(1, writeRes.nRemoved);
// Remove with idhack should return correct results when no collation specified and collection
// has a default collation.
-coll = testDb.collation_remove5;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: "foo"}));
writeRes = coll.remove({_id: "FOO"}, {justOne: true});
assert.commandWorked(writeRes);
@@ -1127,9 +1062,8 @@ assert.eq(1, writeRes.nRemoved);
if (!isClustered) {
// Remove on _id should use idhack stage when query inherits collection default collation.
- coll = testDb.collation_remove6;
coll.drop();
- assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+ assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
explainRes = coll.explain("executionStats").remove({_id: "foo"});
assert.commandWorked(explainRes);
planStage = getPlanStage(explainRes.executionStats.executionStages, "IDHACK");
@@ -1138,10 +1072,9 @@ if (!isClustered) {
// Remove should return correct results when "simple" collation specified and collection has
// a default collation.
-coll = testDb.collation_remove7;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
writeRes = coll.remove({str: "FOO"}, {justOne: true, collation: {locale: "simple"}});
assert.commandWorked(writeRes);
@@ -1149,10 +1082,9 @@ assert.eq(0, writeRes.nRemoved);
// Remove on _id should return correct results when "simple" collation specified and
// collection has a default collation.
-coll = testDb.collation_remove8;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: "foo"}));
writeRes = coll.remove({_id: "FOO"}, {justOne: true, collation: {locale: "simple"}});
assert.commandWorked(writeRes);
@@ -1161,9 +1093,8 @@ assert.eq(0, writeRes.nRemoved);
if (!isClustered) {
// Remove on _id should use idhack stage when explicit query collation matches collection
// default.
- coll = testDb.collation_remove9;
coll.drop();
- assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+ assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
explainRes =
coll.explain("executionStats").remove({_id: "foo"}, {collation: {locale: "en_US"}});
assert.commandWorked(explainRes);
@@ -1172,9 +1103,8 @@ if (!isClustered) {
// Remove on _id should not use idhack stage when query collation does not match collection
// default.
- coll = testDb.collation_remove10;
coll.drop();
- assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+ assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
explainRes =
coll.explain("executionStats").remove({_id: "foo"}, {collation: {locale: "fr_CA"}});
assert.commandWorked(explainRes);
@@ -1187,13 +1117,11 @@ if (!isClustered) {
//
// Update should succeed when collation specified and collection does not exist.
-coll = testDb.collation_update1;
coll.drop();
assert.commandWorked(
coll.update({str: "foo"}, {$set: {other: 99}}, {multi: true, collation: {locale: "fr"}}));
// Update should return correct results when collation specified.
-coll = testDb.collation_update2;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1202,7 +1130,6 @@ writeRes = coll.update(
assert.eq(2, writeRes.nModified);
// Explain of update should return correct results when collation specified.
-coll = testDb.collation_update3;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1217,10 +1144,9 @@ assert.eq(2, planStage.nWouldModify);
// Update should return correct results when no collation specified and collection has a default
// collation.
-coll = testDb.collation_update4;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
writeRes = coll.update({str: "FOO"}, {$set: {other: 99}});
assert.commandWorked(writeRes);
@@ -1228,10 +1154,9 @@ assert.eq(1, writeRes.nMatched);
// Update with idhack should return correct results when no collation specified and collection
// has a default collation.
-coll = testDb.collation_update5;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: "foo"}));
writeRes = coll.update({_id: "FOO"}, {$set: {other: 99}});
assert.commandWorked(writeRes);
@@ -1239,9 +1164,8 @@ assert.eq(1, writeRes.nMatched);
if (!isClustered) {
// Update on _id should use idhack stage when query inherits collection default collation.
- coll = testDb.collation_update6;
coll.drop();
- assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+ assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
explainRes = coll.explain("executionStats").update({_id: "foo"}, {$set: {other: 99}});
assert.commandWorked(explainRes);
planStage = getPlanStage(explainRes.executionStats.executionStages, "IDHACK");
@@ -1250,10 +1174,9 @@ if (!isClustered) {
// Update should return correct results when "simple" collation specified and collection has
// a default collation.
-coll = testDb.collation_update7;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
writeRes = coll.update({str: "FOO"}, {$set: {other: 99}}, {collation: {locale: "simple"}});
assert.commandWorked(writeRes);
@@ -1261,10 +1184,9 @@ assert.eq(0, writeRes.nModified);
// Update on _id should return correct results when "simple" collation specified and
// collection has a default collation.
-coll = testDb.collation_update8;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: "foo"}));
writeRes = coll.update({_id: "FOO"}, {$set: {other: 99}}, {collation: {locale: "simple"}});
assert.commandWorked(writeRes);
@@ -1273,9 +1195,8 @@ assert.eq(0, writeRes.nModified);
if (!isClustered) {
// Update on _id should use idhack stage when explicitly given query collation matches
// collection default.
- coll = testDb.collation_update9;
coll.drop();
- assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+ assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
explainRes = coll.explain("executionStats").update({_id: "foo"}, {$set: {other: 99}}, {
collation: {locale: "en_US"}
});
@@ -1285,9 +1206,8 @@ if (!isClustered) {
// Update on _id should not use idhack stage when query collation does not match collection
// default.
- coll = testDb.collation_update10;
coll.drop();
- assert.commandWorked(testDb.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
+ assert.commandWorked(db.createCollection(coll.getName(), {collation: {locale: "en_US"}}));
explainRes = coll.explain("executionStats").update({_id: "foo"}, {$set: {other: 99}}, {
collation: {locale: "fr_CA"}
});
@@ -1301,9 +1221,8 @@ if (!isClustered) {
//
// $geoNear should fail when collation is specified but the collection does not exist.
-coll = testDb.collation_geonear1;
coll.drop();
-assert.commandFailedWithCode(testDb.runCommand({
+assert.commandFailedWithCode(db.runCommand({
aggregate: coll.getName(),
cursor: {},
pipeline: [{
@@ -1317,10 +1236,9 @@ assert.commandFailedWithCode(testDb.runCommand({
ErrorCodes.NamespaceNotFound);
// $geoNear rejects the now-deprecated "collation" option.
-coll = testDb.collation_geonear2;
coll.drop();
assert.commandWorked(coll.insert({geo: {type: "Point", coordinates: [0, 0]}, str: "abc"}));
-assert.commandFailedWithCode(testDb.runCommand({
+assert.commandFailedWithCode(db.runCommand({
aggregate: coll.getName(),
cursor: {},
pipeline: [{
@@ -1373,20 +1291,18 @@ assert.eq(1, coll.aggregate([geoNearStage], {collation: {locale: "en_US", streng
// $geoNear should return correct results when no collation specified and collection has a
// default collation.
-coll = testDb.collation_geonear3;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.createIndex({geo: "2dsphere"}));
assert.commandWorked(coll.insert({geo: {type: "Point", coordinates: [0, 0]}, str: "abc"}));
assert.eq(1, coll.aggregate([geoNearStage]).itcount());
// $geoNear should return correct results when "simple" collation specified and collection has
// a default collation.
-coll = testDb.collation_geonear4;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.createIndex({geo: "2dsphere"}));
assert.commandWorked(coll.insert({geo: {type: "Point", coordinates: [0, 0]}, str: "abc"}));
assert.eq(0, coll.aggregate([geoNearStage], {collation: {locale: "simple"}}).itcount());
@@ -1397,7 +1313,6 @@ assert.eq(0, coll.aggregate([geoNearStage], {collation: {locale: "simple"}}).itc
// Find with $nearSphere should return correct results when collation specified and
// collection does not exist.
-coll = testDb.collation_nearsphere1;
coll.drop();
assert.eq(
0,
@@ -1407,7 +1322,6 @@ assert.eq(
// Find with $nearSphere should return correct results when collation specified and string
// predicate not indexed.
-coll = testDb.collation_nearsphere2;
coll.drop();
assert.commandWorked(coll.insert({geo: {type: "Point", coordinates: [0, 0]}, str: "abc"}));
assert.commandWorked(coll.createIndex({geo: "2dsphere"}));
@@ -1472,7 +1386,6 @@ assert.eq(
var bulk;
// update().
-coll = testDb.collation_bulkupdate;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1483,7 +1396,6 @@ assert.commandWorked(writeRes);
assert.eq(2, writeRes.nModified);
// updateOne().
-coll = testDb.collation_bulkupdateone;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1494,7 +1406,6 @@ assert.commandWorked(writeRes);
assert.eq(1, writeRes.nModified);
// replaceOne().
-coll = testDb.collation_bulkreplaceone1;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1505,7 +1416,6 @@ assert.commandWorked(writeRes);
assert.eq(1, writeRes.nModified);
// replaceOne() with upsert().
-coll = testDb.collation_bulkreplaceone2;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1524,7 +1434,6 @@ assert.eq(0, writeRes.nUpserted);
assert.eq(1, writeRes.nModified);
// removeOne().
-coll = testDb.collation_bulkremoveone;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1535,7 +1444,6 @@ assert.commandWorked(writeRes);
assert.eq(1, writeRes.nRemoved);
// remove().
-coll = testDb.collation_bulkremove;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1550,7 +1458,6 @@ assert.eq(2, writeRes.nRemoved);
//
// deleteOne().
-coll = testDb.collation_deleteone;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1558,7 +1465,6 @@ res = coll.deleteOne({str: "FOO"}, {collation: {locale: "en_US", strength: 2}});
assert.eq(1, res.deletedCount);
// deleteMany().
-coll = testDb.collation_deletemany;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1566,7 +1472,6 @@ res = coll.deleteMany({str: "FOO"}, {collation: {locale: "en_US", strength: 2}})
assert.eq(2, res.deletedCount);
// findOneAndDelete().
-coll = testDb.collation_findonedelete;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.eq({_id: 1, str: "foo"},
@@ -1574,7 +1479,6 @@ assert.eq({_id: 1, str: "foo"},
assert.eq(null, coll.findOne({_id: 1}));
// findOneAndReplace().
-coll = testDb.collation_findonereplace;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.eq({_id: 1, str: "foo"},
@@ -1583,7 +1487,6 @@ assert.eq({_id: 1, str: "foo"},
assert.neq(null, coll.findOne({str: "bar"}));
// findOneAndUpdate().
-coll = testDb.collation_findoneupdate;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.eq({_id: 1, str: "foo"},
@@ -1592,7 +1495,6 @@ assert.eq({_id: 1, str: "foo"},
assert.neq(null, coll.findOne({other: 99}));
// replaceOne().
-coll = testDb.collation_replaceone;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1600,7 +1502,6 @@ res = coll.replaceOne({str: "FOO"}, {str: "bar"}, {collation: {locale: "en_US",
assert.eq(1, res.modifiedCount);
// updateOne().
-coll = testDb.collation_updateone;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1609,7 +1510,6 @@ res =
assert.eq(1, res.modifiedCount);
// updateMany().
-coll = testDb.collation_updatemany;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1618,7 +1518,6 @@ res =
assert.eq(2, res.modifiedCount);
// updateOne with bulkWrite().
-coll = testDb.collation_updateonebulkwrite;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1645,7 +1544,6 @@ for (let backwards of [undefined, null]) {
}
// updateMany with bulkWrite().
-coll = testDb.collation_updatemanybulkwrite;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1659,7 +1557,6 @@ res = coll.bulkWrite([{
assert.eq(2, res.matchedCount);
// replaceOne with bulkWrite().
-coll = testDb.collation_replaceonebulkwrite;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1670,7 +1567,6 @@ res = coll.bulkWrite([{
assert.eq(1, res.matchedCount);
// deleteOne with bulkWrite().
-coll = testDb.collation_deleteonebulkwrite;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1679,7 +1575,6 @@ res = coll.bulkWrite(
assert.eq(1, res.deletedCount);
// deleteMany with bulkWrite().
-coll = testDb.collation_deletemanybulkwrite;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "foo"}));
@@ -1688,7 +1583,6 @@ res = coll.bulkWrite(
assert.eq(2, res.deletedCount);
// Two deleteOne ops with bulkWrite using different collations.
-coll = testDb.collation_deleteone2collation;
coll.drop();
assert.commandWorked(coll.insert({_id: 1, str: "foo"}));
assert.commandWorked(coll.insert({_id: 2, str: "bar"}));
@@ -1700,19 +1594,18 @@ assert.eq(2, res.deletedCount);
// applyOps.
if (!isMongos) {
- coll = testDb.collation_applyops;
coll.drop();
assert.commandWorked(
- testDb.createCollection(coll.getName(), {collation: {locale: "en_US", strength: 2}}));
+ db.createCollection("collation", {collation: {locale: "en_US", strength: 2}}));
assert.commandWorked(coll.insert({_id: "foo", x: 5, str: "bar"}));
// preCondition.q respects collection default collation.
- assert.commandFailed(testDb.runCommand({
+ assert.commandFailed(db.runCommand({
applyOps: [{op: "u", ns: coll.getFullName(), o2: {_id: "foo"}, o: {$set: {x: 6}}}],
preCondition: [{ns: coll.getFullName(), q: {_id: "not foo"}, res: {str: "bar"}}]
}));
assert.eq(5, coll.findOne({_id: "foo"}).x);
- assert.commandWorked(testDb.runCommand({
+ assert.commandWorked(db.runCommand({
applyOps: [{op: "u", ns: coll.getFullName(), o2: {_id: "foo"}, o: {$set: {x: 6}}}],
preCondition: [{ns: coll.getFullName(), q: {_id: "FOO"}, res: {str: "bar"}}]
}));
@@ -1740,16 +1633,15 @@ if (!isMongos) {
// default collation of the corresponding collection. We skip running this command in a sharded
// cluster because it isn't supported by mongos.
if (!isMongos) {
- const clonedColl = testDb.collation_cloned;
+ const clonedColl = db.collation_cloned;
- coll = testDb.collation_orig;
coll.drop();
clonedColl.drop();
// Create a collection with a non-simple default collation.
assert.commandWorked(
- testDb.runCommand({create: coll.getName(), collation: {locale: "en", strength: 2}}));
- const originalCollectionInfos = testDb.getCollectionInfos({name: coll.getName()});
+ db.runCommand({create: coll.getName(), collation: {locale: "en", strength: 2}}));
+ const originalCollectionInfos = db.getCollectionInfos({name: coll.getName()});
assert.eq(originalCollectionInfos.length, 1, tojson(originalCollectionInfos));
assert.commandWorked(coll.insert({_id: "FOO"}));
@@ -1758,10 +1650,10 @@ if (!isMongos) {
coll.find({_id: "foo"}).toArray(),
"query should have performed a case-insensitive match");
- var cloneCollOutput = testDb.runCommand(
+ var cloneCollOutput = db.runCommand(
{cloneCollectionAsCapped: coll.getName(), toCollection: clonedColl.getName(), size: 4096});
assert.commandWorked(cloneCollOutput);
- const clonedCollectionInfos = testDb.getCollectionInfos({name: clonedColl.getName()});
+ const clonedCollectionInfos = db.getCollectionInfos({name: clonedColl.getName()});
assert.eq(clonedCollectionInfos.length, 1, tojson(clonedCollectionInfos));
assert.eq(originalCollectionInfos[0].options.collation,
clonedCollectionInfos[0].options.collation);
@@ -1769,7 +1661,6 @@ if (!isMongos) {
}
// Test that the find command's min/max options respect the collation.
-coll = testDb.collation_minmax1;
coll.drop();
assert.commandWorked(coll.insert({str: "a"}));
assert.commandWorked(coll.insert({str: "A"}));
@@ -1830,7 +1721,6 @@ assert.eq(4,
.itcount());
// Ensure results from index with min/max query are sorted to match requested collation.
-coll = testDb.collation_minmax2;
coll.drop();
assert.commandWorked(coll.createIndex({a: 1, b: 1}));
assert.commandWorked(
@@ -1865,7 +1755,7 @@ explainRes = coll.find({}, {_id: 0})
.sort({a: 1, b: 1})
.explain();
assert.commandWorked(explainRes);
-assert(planHasStage(testDb, getWinningPlan(explainRes.queryPlanner), "SORT"));
+assert(planHasStage(db, getWinningPlan(explainRes.queryPlanner), "SORT"));
// This query should fail since min has a string as one of it's boundaries, and the
// collation doesn't match that of the index.
diff --git a/jstests/core/collection_uuid_coll_mod.js b/jstests/core/collection_uuid_coll_mod.js
index 218a758c0b3..52da75bb345 100644
--- a/jstests/core/collection_uuid_coll_mod.js
+++ b/jstests/core/collection_uuid_coll_mod.js
@@ -57,7 +57,7 @@ assert.eq(res.actualCollection, null);
// 5. The command fails when the provided UUID corresponds to a different collection, even if the
// provided namespace does not exist.
-assert.commandWorked(testDB.runCommand({drop: coll2.getName()}));
+coll2.drop();
res = assert.commandFailedWithCode(
testDB.runCommand({collMod: coll2.getName(), collectionUUID: uuid}),
ErrorCodes.CollectionUUIDMismatch);
@@ -65,15 +65,4 @@ assert.eq(res.db, testDB.getName());
assert.eq(res.collectionUUID, uuid);
assert.eq(res.expectedCollection, coll2.getName());
assert.eq(res.actualCollection, coll.getName());
-assert(!testDB.getCollectionNames().includes(coll2.getName()));
-
-// 6. The command fails with CollectionUUIDMismatch even if the database does not exist.
-const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
-res = assert.commandFailedWithCode(
- nonexistentDB.runCommand({collMod: 'nonexistent', collectionUUID: uuid}),
- ErrorCodes.CollectionUUIDMismatch);
-assert.eq(res.db, nonexistentDB.getName());
-assert.eq(res.collectionUUID, uuid);
-assert.eq(res.expectedCollection, 'nonexistent');
-assert.eq(res.actualCollection, null);
})();
diff --git a/jstests/core/collection_uuid_drop.js b/jstests/core/collection_uuid_drop.js
index a3465795292..276f591afdf 100644
--- a/jstests/core/collection_uuid_drop.js
+++ b/jstests/core/collection_uuid_drop.js
@@ -58,24 +58,13 @@ assert.eq(res.actualCollection, null);
// The command fails when the provided UUID corresponds to a different collection, even if the
// provided namespace does not exist.
-assert.commandWorked(testDB.runCommand({drop: coll2.getName()}));
+coll2.drop();
res = assert.commandFailedWithCode(testDB.runCommand({drop: coll2.getName(), collectionUUID: uuid}),
ErrorCodes.CollectionUUIDMismatch);
assert.eq(res.db, testDB.getName());
assert.eq(res.collectionUUID, uuid);
assert.eq(res.expectedCollection, coll2.getName());
assert.eq(res.actualCollection, coll.getName());
-assert(!testDB.getCollectionNames().includes(coll2.getName()));
-
-// The command fails with CollectionUUIDMismatch even if the database does not exist.
-const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
-res = assert.commandFailedWithCode(
- nonexistentDB.runCommand({drop: 'nonexistent', collectionUUID: uuid}),
- ErrorCodes.CollectionUUIDMismatch);
-assert.eq(res.db, nonexistentDB.getName());
-assert.eq(res.collectionUUID, uuid);
-assert.eq(res.expectedCollection, 'nonexistent');
-assert.eq(res.actualCollection, null);
// The command fails when the provided UUID corresponds to a different collection, even if the
// provided namespace is a view.
diff --git a/jstests/core/collection_uuid_find.js b/jstests/core/collection_uuid_find.js
index 241435c1350..f3ce69f0e34 100644
--- a/jstests/core/collection_uuid_find.js
+++ b/jstests/core/collection_uuid_find.js
@@ -56,25 +56,13 @@ assert.eq(res.actualCollection, null);
// The command fails when the provided UUID corresponds to a different collection, even if the
// provided namespace does not exist.
-assert.commandWorkedOrFailedWithCode(testDB.runCommand({drop: coll2.getName()}),
- ErrorCodes.NamespaceNotFound);
+coll2.drop();
res = assert.commandFailedWithCode(testDB.runCommand({find: coll2.getName(), collectionUUID: uuid}),
ErrorCodes.CollectionUUIDMismatch);
assert.eq(res.db, testDB.getName());
assert.eq(res.collectionUUID, uuid);
assert.eq(res.expectedCollection, coll2.getName());
assert.eq(res.actualCollection, coll.getName());
-assert(!testDB.getCollectionNames().includes(coll2.getName()));
-
-// The command fails with CollectionUUIDMismatch even if the database does not exist.
-const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
-res = assert.commandFailedWithCode(
- nonexistentDB.runCommand({find: 'nonexistent', collectionUUID: uuid}),
- ErrorCodes.CollectionUUIDMismatch);
-assert.eq(res.db, nonexistentDB.getName());
-assert.eq(res.collectionUUID, uuid);
-assert.eq(res.expectedCollection, 'nonexistent');
-assert.eq(res.actualCollection, null);
// The command fails when the provided UUID corresponds to a different collection, even if the
// provided namespace is a view.
diff --git a/jstests/core/collection_uuid_index_commands.js b/jstests/core/collection_uuid_index_commands.js
index 85c9f0a9124..a323859144c 100644
--- a/jstests/core/collection_uuid_index_commands.js
+++ b/jstests/core/collection_uuid_index_commands.js
@@ -4,7 +4,6 @@
* @tags: [
* requires_fcv_60,
* tenant_migration_incompatible,
- * requires_non_retryable_commands,
* ]
*/
(function() {
@@ -21,6 +20,12 @@ const validateErrorResponse = function(
// In sharded cluster scenario, the inner raw shards reply should contain the error info,
// along with the outer reply obj.
for (let [_, shardReply] of Object.entries(res.raw)) {
+ if (shardReply.code === ErrorCodes.HostUnreachable) {
+ // We can hit this error on some suites that kills the primary node on shards.
+ // Skipping is safe as this is rare and most probably happens on one shard.
+ continue;
+ }
+
assert.eq(shardReply.code, ErrorCodes.CollectionUUIDMismatch);
assert.eq(shardReply.db, db);
assert.eq(shardReply.collectionUUID, collectionUUID);
@@ -77,19 +82,10 @@ const testCommand = function(cmd, cmdObj) {
jsTestLog("The command '" + cmd +
"' fails when the provided UUID corresponds to a different collection, even if the " +
"provided namespace does not exist.");
- assert.commandWorked(testDB.runCommand({drop: coll2.getName()}));
+ coll2.drop();
res =
assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch);
validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName());
- assert(!testDB.getCollectionNames().includes(coll2.getName()));
-
- jsTestLog("The command '" + cmd +
- "' fails with CollectionUUIDMismatch even if the database does not exist.");
- const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
- cmdObj[cmd] = 'nonexistent';
- res = assert.commandFailedWithCode(nonexistentDB.runCommand(cmdObj),
- ErrorCodes.CollectionUUIDMismatch);
- validateErrorResponse(res, nonexistentDB.getName(), uuid, 'nonexistent', null);
jsTestLog("Only collections in the same database are specified by actualCollection.");
const otherDB = testDB.getSiblingDB(testDB.getName() + '_2');
diff --git a/jstests/core/collection_uuid_rename_collection.js b/jstests/core/collection_uuid_rename_collection.js
index bc294fd7aab..3dc99fe98ab 100644
--- a/jstests/core/collection_uuid_rename_collection.js
+++ b/jstests/core/collection_uuid_rename_collection.js
@@ -162,7 +162,7 @@ assert.eq(res.actualCollection, null);
// The command fails when the provided UUID corresponds to a different collection, even if the
// provided source namespace does not exist.
-assert.commandWorked(testDB.runCommand({drop: coll2.getName()}));
+coll2.drop();
res = assert.commandFailedWithCode(testDB.adminCommand({
renameCollection: coll2.getFullName(),
to: coll3.getFullName(),
@@ -174,21 +174,6 @@ assert.eq(res.db, testDB.getName());
assert.eq(res.collectionUUID, uuid(coll));
assert.eq(res.expectedCollection, coll2.getName());
assert.eq(res.actualCollection, coll.getName());
-assert(!testDB.getCollectionNames().includes(coll2.getName()));
-
-// The command fails with CollectionUUIDMismatch even if the database does not exist.
-const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
-res = assert.commandFailedWithCode(testDB.adminCommand({
- renameCollection: nonexistentDB.getName() + '.nonexistent',
- to: nonexistentDB.getName() + '.nonexistent_2',
- dropTarget: true,
- collectionUUID: uuid(coll),
-}),
- ErrorCodes.CollectionUUIDMismatch);
-assert.eq(res.db, nonexistentDB.getName());
-assert.eq(res.collectionUUID, uuid(coll));
-assert.eq(res.expectedCollection, 'nonexistent');
-assert.eq(res.actualCollection, null);
// The collectionUUID parameter cannot be provided when renaming a collection between databases.
const otherDBColl = db.getSiblingDB(jsTestName() + '_2').coll;
diff --git a/jstests/core/collection_uuid_write_commands.js b/jstests/core/collection_uuid_write_commands.js
index 080ce1772d5..03bd0b09ae7 100644
--- a/jstests/core/collection_uuid_write_commands.js
+++ b/jstests/core/collection_uuid_write_commands.js
@@ -57,20 +57,10 @@ var testCommand = function(cmd, cmdObj) {
jsTestLog("The command '" + cmd +
"' fails when the provided UUID corresponds to a different collection, even if the " +
"provided namespace does not exist.");
- assert.commandWorkedOrFailedWithCode(testDB.runCommand({drop: coll2.getName()}),
- ErrorCodes.NamespaceNotFound);
+ coll2.drop();
res =
assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch);
validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName());
- assert(!testDB.getCollectionNames().includes(coll2.getName()));
-
- jsTestLog("The command '" + cmd +
- "' fails with CollectionUUIDMismatch even if the database does not exist.");
- const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
- cmdObj[cmd] = 'nonexistent';
- res = assert.commandFailedWithCode(nonexistentDB.runCommand(cmdObj),
- ErrorCodes.CollectionUUIDMismatch);
- validateErrorResponse(res, nonexistentDB.getName(), uuid, 'nonexistent', null);
jsTestLog("Only collections in the same database are specified by actualCollection.");
const otherDB = testDB.getSiblingDB(testDB.getName() + '_2');
@@ -85,7 +75,5 @@ var testCommand = function(cmd, cmdObj) {
testCommand("insert", {insert: "", documents: [{inserted: true}]});
testCommand("update", {update: "", updates: [{q: {_id: 0}, u: {$set: {updated: true}}}]});
-testCommand("update",
- {update: "", updates: [{q: {_id: 0}, u: {$set: {updated: true}}, upsert: true}]});
testCommand("delete", {delete: "", deletes: [{q: {_id: 0}, limit: 1}]});
})();
diff --git a/jstests/core/collmod.js b/jstests/core/collmod.js
index 3362650a77a..4362fc110a4 100644
--- a/jstests/core/collmod.js
+++ b/jstests/core/collmod.js
@@ -131,17 +131,3 @@ assert.commandFailed(
// Fails with an unknown key pattern.
assert.commandFailed(db.runCommand(
{collmod: coll, index: {keyPattern: {doesnotexist: 1}, expireAfterSeconds: 100}}));
-
-// Exclude from multiversion suites as SERVER-84531 will not be backported to older versions
-const isMultiversion = jsTestOptions().mixedBinVersions || jsTestOptions().shardMixedBinVersions ||
- jsTestOptions().useRandomBinVersionsWithinReplicaSet;
-if (!isMultiversion) {
- // The timeseriesBucketsMayHaveMixedSchemaData option can only be used on time-series
- // collections.
- assert.commandFailedWithCode(
- db.runCommand({collMod: coll, timeseriesBucketsMayHaveMixedSchemaData: true}),
- ErrorCodes.InvalidOptions);
- assert.commandFailedWithCode(
- db.runCommand({collMod: coll, timeseriesBucketsMayHaveMixedSchemaData: false}),
- ErrorCodes.InvalidOptions);
-}
diff --git a/jstests/core/collmod_convert_index_uniqueness.js b/jstests/core/collmod_convert_index_uniqueness.js
index 559a5fed82c..fc6588ae70c 100644
--- a/jstests/core/collmod_convert_index_uniqueness.js
+++ b/jstests/core/collmod_convert_index_uniqueness.js
@@ -5,7 +5,7 @@
* # Cannot implicitly shard accessed collections because of collection existing when none
* # expected.
* assumes_no_implicit_collection_creation_after_drop, # common tag in collMod tests.
- * requires_fcv_60,
+ * requires_fcv_52,
* requires_non_retryable_commands, # common tag in collMod tests.
* # TODO(SERVER-61181): Fix validation errors under ephemeralForTest.
* incompatible_with_eft,
@@ -19,9 +19,12 @@
(function() {
'use strict';
-load("jstests/libs/feature_flag_util.js");
+const collModIndexUniqueEnabled = assert
+ .commandWorked(db.getMongo().adminCommand(
+ {getParameter: 1, featureFlagCollModIndexUnique: 1}))
+ .featureFlagCollModIndexUnique.value;
-if (!FeatureFlagUtil.isEnabled(db, "CollModIndexUnique")) {
+if (!collModIndexUniqueEnabled) {
jsTestLog('Skipping test because the collMod unique index feature flag is disabled.');
return;
}
diff --git a/jstests/core/collmod_convert_to_ttl.js b/jstests/core/collmod_convert_to_ttl.js
index c4c8b7d2bbd..ab617d3eeb7 100644
--- a/jstests/core/collmod_convert_to_ttl.js
+++ b/jstests/core/collmod_convert_to_ttl.js
@@ -39,6 +39,13 @@ assert.commandFailedWithCode(
db.runCommand({"collMod": collName, "index": {"keyPattern": {a: 1}, "expireAfterSeconds": -1}}),
ErrorCodes.InvalidOptions);
+// Tries to modify with an 'expireAfterSeconds' value too large.
+assert.commandFailedWithCode(db.runCommand({
+ "collMod": collName,
+ "index": {"keyPattern": {a: 1}, "expireAfterSeconds": 10000000000000}
+}),
+ ErrorCodes.InvalidOptions);
+
// Successfully converts to a TTL index.
assert.commandWorked(db.runCommand(
{"collMod": collName, "index": {"keyPattern": {a: 1}, "expireAfterSeconds": 100}}));
diff --git a/jstests/core/collmod_convert_to_unique_apply_ops.js b/jstests/core/collmod_convert_to_unique_apply_ops.js
index eb574081840..3e47f117512 100644
--- a/jstests/core/collmod_convert_to_unique_apply_ops.js
+++ b/jstests/core/collmod_convert_to_unique_apply_ops.js
@@ -23,9 +23,12 @@
(function() {
'use strict';
-load("jstests/libs/feature_flag_util.js");
+const collModIndexUniqueEnabled = assert
+ .commandWorked(db.getMongo().adminCommand(
+ {getParameter: 1, featureFlagCollModIndexUnique: 1}))
+ .featureFlagCollModIndexUnique.value;
-if (!FeatureFlagUtil.isEnabled(db, "CollModIndexUnique")) {
+if (!collModIndexUniqueEnabled) {
jsTestLog('Skipping test because the collMod unique index feature flag is disabled.');
return;
}
diff --git a/jstests/core/collmod_convert_to_unique_violations.js b/jstests/core/collmod_convert_to_unique_violations.js
index 84e29d106c8..52b369e7063 100644
--- a/jstests/core/collmod_convert_to_unique_violations.js
+++ b/jstests/core/collmod_convert_to_unique_violations.js
@@ -20,10 +20,14 @@
(function() {
'use strict';
-load("jstests/libs/feature_flag_util.js");
load("jstests/libs/fixture_helpers.js"); // For 'isMongos'
-if (!FeatureFlagUtil.isEnabled(db, "CollModIndexUnique")) {
+const collModIndexUniqueEnabled = assert
+ .commandWorked(db.getMongo().adminCommand(
+ {getParameter: 1, featureFlagCollModIndexUnique: 1}))
+ .featureFlagCollModIndexUnique.value;
+
+if (!collModIndexUniqueEnabled) {
jsTestLog('Skipping test because the collMod unique index feature flag is disabled.');
return;
}
@@ -100,4 +104,4 @@ assertFailedWithViolations({a: 1, b: 1}, [{ids: [4, 9]}, {ids: [6, 7, 8]}]);
assert.commandWorked(coll.insert({_id: "10", a: 101, b: 4}));
assertFailedWithViolations({a: 1, b: 1}, [{ids: [4, 9, "10"]}, {ids: [6, 7, 8]}]);
-})();
+})(); \ No newline at end of file
diff --git a/jstests/core/command_let_variables.js b/jstests/core/command_let_variables.js
index 72d6558f6ce..1e4286dbc19 100644
--- a/jstests/core/command_let_variables.js
+++ b/jstests/core/command_let_variables.js
@@ -6,15 +6,13 @@
(function() {
"use strict";
-load("jstests/libs/analyze_plan.js");
load("jstests/libs/fixture_helpers.js"); // For 'isMongos' and 'isSharded'.
const testDB = db.getSiblingDB("command_let_variables");
const coll = testDB.command_let_variables;
-coll.drop();
+const targetColl = testDB.command_let_variables_target;
-const isMongos = FixtureHelpers.isMongos(testDB);
-const isCollSharded = FixtureHelpers.isSharded(coll);
+assert.commandWorked(testDB.dropDatabase());
const testDocs = [
{
@@ -84,20 +82,7 @@ expectedResults = [
assert.eq(coll.aggregate(pipeline, {let : {target_trend: "weak decline"}}).toArray(),
expectedResults);
-// Test that running explain on the agg command works as expected.
-let explain = assert.commandWorked(testDB.runCommand({
- explain:
- {aggregate: coll.getName(), pipeline, let : {target_trend: "weak decline"}, cursor: {}},
- verbosity: "executionStats"
-}));
-if (!isMongos) {
- assert(explain.hasOwnProperty("stages"), explain);
- assert.neq(explain.stages.length, 0, explain);
- let lastStage = explain.stages[explain.stages.length - 1];
- assert.eq(lastStage.nReturned, 2, explain);
-}
-
-if (!isMongos) {
+if (!FixtureHelpers.isMongos(testDB)) {
// Test that if runtimeConstants and let are both specified, both will coexist.
// Runtime constants are not allowed on mongos passthroughs.
let constants = {
@@ -277,20 +262,6 @@ expectedResults = {
assert.eq(result.length, 1);
assert.eq(expectedResults, result[0]);
-// Test that let parameters work as expected when the find is run as an explain.
-explain = assert.commandWorked(testDB.runCommand({
- explain: {
- find: coll.getName(),
- let : {target_species: "Song Thrush (Turdus philomelos)"},
- filter: {$expr: {$eq: ["$Species", "$$target_species"]}},
- projection: {_id: 0}
- },
- verbosity: "executionStats"
-}));
-if (!isMongos) {
- assert.eq(explain.executionStats.nReturned, 1, explain);
-}
-
// Delete tests with let params will delete a record, assert that a point-wise find yields an empty
// result, and then restore the collection state for further tests down the line. We can't exercise
// a multi-delete here (limit: 0) because of failures in sharded txn passthrough tests.
@@ -306,24 +277,8 @@ result = assert
.cursor.firstBatch;
assert.eq(result.length, 0);
-assert.commandWorked(coll.insert({_id: 4, Species: "bird_to_remove"}));
-
-// Test that explain of a delete command works as expected with 'let' parameters.
-explain = assert.commandWorked(testDB.runCommand({
- explain: {
- delete: coll.getName(),
- let : {target_species: "bird_to_remove"},
- deletes:
- [{q: {$and: [{_id: 4}, {$expr: {$eq: ["$Species", "$$target_species"]}}]}, limit: 1}]
- },
- verbosity: "executionStats"
-}));
-if (!isMongos) {
- let deleteStage = getPlanStage(explain.executionStats.executionStages, "DELETE");
- assert.eq(deleteStage.nWouldDelete, 1, explain);
-}
-
// Test that the .remove() shell helper supports let parameters.
+assert.commandWorked(coll.insert({_id: 4, Species: "bird_to_remove"}));
result = assert.commandWorked(
coll.remove({$and: [{_id: 4}, {$expr: {$eq: ["$Species", "$$target_species"]}}]},
{justOne: true, let : {target_species: "bird_to_remove"}}));
@@ -365,67 +320,43 @@ assert.commandFailedWithCode(
{aggregate: coll.getName(), pipeline: [], cursor: {}, let : {REMOVE: "failure"}}),
ErrorCodes.FailedToParse);
-// Test that let variables can be used within views. Skip in sharded collection passthroughs, since
-// dropping the view namespace implicitly recreates the namespace as a sharded collection.
-if (!isCollSharded) {
- const viewName = "core-viewColl";
- testDB[viewName].drop();
- assert.commandWorked(testDB.runCommand({
- create: viewName,
- viewOn: coll.getName(),
- pipeline: [{$match: {Species: "Song Thrush (Turdus philomelos)"}}]
- }));
- assert.commandWorked(testDB.runCommand({
- aggregate: viewName,
- pipeline: [{$addFields: {var : "$$variable"}}],
- let : {variable: "Song Thrush"},
- cursor: {}
- }));
-}
-
-assert.commandWorked(coll.insert({_id: 5, Species: "spy_bird"}));
-
-// Test that explain of findAndModify works correctly with let parameters.
-explain = assert.commandWorked(testDB.runCommand({
- explain: {
- findAndModify: coll.getName(),
- let : {target_species: "spy_bird"},
- // Querying on _id field for sharded collection passthroughs.
- query: {$and: [{_id: 5}, {$expr: {$eq: ["$Species", "$$target_species"]}}]},
- update: {Species: "questionable_bird"},
- new: true
- },
- verbosity: "executionStats"
+// Test that let variables can be used within views.
+assert.commandWorked(testDB.runCommand({
+ create: "core-viewColl",
+ viewOn: coll.getName(),
+ pipeline: [{$match: {Species: "Song Thrush (Turdus philomelos)"}}]
+}));
+assert.commandWorked(testDB.runCommand({
+ aggregate: "core-viewColl",
+ pipeline: [{$addFields: {var : "$$variable"}}],
+ let : {variable: "Song Thrush"},
+ cursor: {}
}));
-if (!isMongos) {
- let updateStage = getPlanStage(explain.executionStats.executionStages, "UPDATE");
- assert.eq(updateStage.nMatched, 1, explain);
- assert.eq(updateStage.nWouldModify, 1, explain);
-}
// Test that findAndModify works correctly with let parameter arguments.
-result = assert.commandWorked(testDB.runCommand({
+assert.commandWorked(coll.insert({_id: 5, Species: "spy_bird"}));
+result = testDB.runCommand({
findAndModify: coll.getName(),
let : {target_species: "spy_bird"},
// Querying on _id field for sharded collection passthroughs.
query: {$and: [{_id: 5}, {$expr: {$eq: ["$Species", "$$target_species"]}}]},
update: {Species: "questionable_bird"},
new: true
-}));
+});
expectedResults = {
_id: 5,
Species: "questionable_bird"
};
assert.eq(expectedResults, result.value, result);
-result = assert.commandWorked(testDB.runCommand({
+result = testDB.runCommand({
findAndModify: coll.getName(),
let : {species_name: "not_a_bird", realSpecies: "dino"},
// Querying on _id field for sharded collection passthroughs.
query: {$and: [{_id: 5}, {$expr: {$eq: ["$Species", "questionable_bird"]}}]},
update: [{$project: {Species: "$$species_name"}}, {$addFields: {suspect: "$$realSpecies"}}],
new: true
-}));
+});
expectedResults = {
_id: 5,
Species: "not_a_bird",
@@ -433,31 +364,12 @@ expectedResults = {
};
assert.eq(expectedResults, result.value, result);
-// Test that explain of update works correctly with let parameters.
-explain = assert.commandWorked(testDB.runCommand({
- explain: {
- update: coll.getName(),
- updates: [{
- q: {_id: 3, $expr: {$eq: ["$Species", "$$target_species"]}},
- u: [{$set: {Species: "$$new_name"}}],
- }],
- let : {target_species: "Chaffinch (Fringilla coelebs)", new_name: "Chaffinch"}
- },
- verbosity: "executionStats"
-}));
-if (!isMongos) {
- let updateStage = getPlanStage(explain.executionStats.executionStages, "UPDATE");
- assert.eq(updateStage.nMatched, 1, explain);
- assert.eq(updateStage.nWouldModify, 1, explain);
-}
-
// Test that update respects different parameters in both the query and update part.
result = assert.commandWorked(testDB.runCommand({
update: coll.getName(),
- updates: [{
- q: {_id: 3, $expr: {$eq: ["$Species", "$$target_species"]}},
- u: [{$set: {Species: "$$new_name"}}],
- }],
+ updates: [
+ {q: {$expr: {$eq: ["$Species", "$$target_species"]}}, u: [{$set: {Species: "$$new_name"}}]}
+ ],
let : {target_species: "Chaffinch (Fringilla coelebs)", new_name: "Chaffinch"}
}));
assert.eq(result.n, 1);
@@ -475,8 +387,8 @@ assert.eq(result.cursor.firstBatch.length, 1);
result = assert.commandWorked(testDB.runCommand({
update: coll.getName(),
updates: [{
- q: {_id: 3, $expr: {$eq: ["$Species", "$$target_species"]}},
- u: [{$set: {Timestamp: "$$NOW"}}, {$set: {Species: "$$new_name"}}],
+ q: {$expr: {$eq: ["$Species", "$$target_species"]}},
+ u: [{$set: {Timestamp: "$$NOW"}}, {$set: {Species: "$$new_name"}}]
}],
let : {target_species: "Chaffinch", new_name: "Pied Piper"}
}));
@@ -491,12 +403,6 @@ result = assert.commandWorked(
testDB.runCommand({find: coll.getName(), filter: {$expr: {$eq: ["$Species", "Pied Piper"]}}}));
assert.eq(result.cursor.firstBatch.length, 1, result);
-// This forces a multi-statement transaction to commit if this test is running in one of the
-// multi-statement transaction passthrough suites. We need to do this to ensure the updates above
-// commit before running an update that will fail, as the failed update aborts the entire
-// transaction and rolls back the updates above.
-assert.commandWorked(testDB.runCommand({ping: 1}));
-
// Test that undefined let params in the update's query part fail gracefully.
assert.commandFailedWithCode(testDB.runCommand({
update: coll.getName(),
@@ -512,8 +418,8 @@ assert.commandFailedWithCode(testDB.runCommand({
assert.commandFailedWithCode(testDB.runCommand({
update: coll.getName(),
updates: [{
- q: {_id: 3, $expr: {$eq: ["$Species", "Chaffinch (Fringilla coelebs)"]}},
- u: [{$set: {Species: "$$new_name"}}],
+ q: {$expr: {$eq: ["$Species", "Chaffinch (Fringilla coelebs)"]}},
+ u: [{$set: {Species: "$$new_name"}}]
}],
let : {cat: "not_a_bird"}
}),
@@ -521,7 +427,7 @@ assert.commandFailedWithCode(testDB.runCommand({
// Test that the .update() shell helper supports let parameters.
result = assert.commandWorked(
- coll.update({_id: 3, $expr: {$eq: ["$Species", "$$target_species"]}},
+ coll.update({$expr: {$eq: ["$Species", "$$target_species"]}},
[{$set: {Species: "$$new_name"}}],
{let : {target_species: "Pied Piper", new_name: "Chaffinch"}}));
assert.eq(result.nMatched, 1);
@@ -613,10 +519,7 @@ assert.between(0, result, 1);
}
// Test that the expressions are evaluated once up front.
-//
-// TODO SERVER-75927: This does not work as expected when the collection is sharded. Once the bug
-// is fixed, we should re-enable this test case when the collection is sharded.
-if (!isCollSharded) {
+{
const values = assert
.commandWorked(testDB.runCommand({
find: coll.getName(),
diff --git a/jstests/core/command_let_variables_expressions.js b/jstests/core/command_let_variables_expressions.js
deleted file mode 100644
index c551c30be48..00000000000
--- a/jstests/core/command_let_variables_expressions.js
+++ /dev/null
@@ -1,208 +0,0 @@
-// Tests that commands like find, aggregate and update accept a 'let' parameter which defines
-// variables for use in expressions within the command. Specifically covers cases where the
-// parameter definitions contain expressions.
-// @tags: [
-// requires_non_retryable_writes,
-// does_not_support_transactions,
-// tenant_migration_incompatible
-// ]
-(function() {
-"use strict";
-
-load('jstests/aggregation/extras/utils.js'); // For assertArrayEq().
-
-const coll = db.getCollection('command_let_variables_expressions');
-
-function setupColl() {
- coll.drop();
- assert.commandWorked(coll.insert([
- {_id: 2, a: {}},
- {_id: 3, b: 1},
- {_id: 4, a: "$notAFieldPath"},
- ]));
-}
-setupColl();
-
-const missingLetParam = {
- $getField: {field: "c", input: {a: 1}}
-};
-const literalLetParam = {
- $literal: "$notAFieldPath"
-};
-
-// Run find commands with 'let' parameters containing expressions.
-{
- // 'let' parameter expression that resolves to a missing value should not cause a query error.
- let result = assert.commandWorked(db.runCommand({
- find: coll.getName(),
- filter: {$expr: {$eq: ["$a", "$$c"]}},
- let : {c: missingLetParam},
- }));
- assertArrayEq({
- actual: result.cursor.firstBatch,
- expected: [{_id: 3, b: 1}],
- });
-
- // 'let' parameter expression that includes $literal and a $-prefixed string should not be
- // misinterpreted as a field path.
- result = assert.commandWorked(db.runCommand({
- find: coll.getName(),
- filter: {$expr: {$eq: ["$a", "$$c"]}},
- let : {c: literalLetParam},
- }));
- assertArrayEq({
- actual: result.cursor.firstBatch,
- expected: [{_id: 4, a: "$notAFieldPath"}],
- });
-}
-
-// Run aggregate commands with 'let' parameters containing expressions.
-{
- let result =
- coll.aggregate([{$match: {$expr: {$eq: ["$a", "$$c"]}}}], {let : {c: missingLetParam}})
- .toArray();
- assertArrayEq({
- actual: result,
- expected: [{_id: 3, b: 1}],
- });
-
- result = coll.aggregate([{$match: {$expr: {$eq: ["$a", "$$c"]}}}], {let : {c: literalLetParam}})
- .toArray();
- assertArrayEq({
- actual: result,
- expected: [{_id: 4, a: "$notAFieldPath"}],
- });
-}
-
-// Same thing but for update.
-{
- assert.commandWorked(db.runCommand({
- update: coll.getName(),
- updates: [{
- q: {$expr: {$eq: ["$a", "$$c"]}},
- u: [{$set: {c: "updated"}}],
- multi: true,
- }],
- let : {c: missingLetParam}
- }));
- assertArrayEq({
- actual: coll.find().toArray(),
- expected: [{_id: 2, a: {}}, {_id: 3, b: 1, c: "updated"}, {_id: 4, a: "$notAFieldPath"}],
- });
-
- // Undo changes.
- setupColl();
-
- assert.commandWorked(db.runCommand({
- update: coll.getName(),
- updates: [{
- q: {$expr: {$eq: ["$a", "$$c"]}},
- u: [{$set: {c: "updated"}}],
- multi: true,
- }],
- let : {c: literalLetParam}
- }));
- assertArrayEq({
- actual: coll.find().toArray(),
- expected: [
- {_id: 2, a: {}},
- {_id: 3, b: 1},
- {_id: 4, a: "$notAFieldPath", c: "updated"},
- ],
- });
-}
-
-// Run findAndModify commands with 'let' parameters containing expressions.
-{
- setupColl();
-
- assert.commandWorked(db.runCommand({
- findAndModify: coll.getName(),
- query: {_id: 3, $expr: {$eq: ["$a", "$$c"]}},
- update: [{$set: {c: "updated"}}],
- let : {c: missingLetParam}
- }));
- assertArrayEq({
- actual: coll.find().toArray(),
- expected: [{_id: 2, a: {}}, {_id: 3, b: 1, c: "updated"}, {_id: 4, a: "$notAFieldPath"}],
- });
-
- // Undo changes.
- setupColl();
-
- assert.commandWorked(db.runCommand({
- findAndModify: coll.getName(),
- query: {_id: 4, $expr: {$eq: ["$a", "$$c"]}},
- update: [{$set: {c: "updated"}}],
- let : {c: literalLetParam}
- }));
- assertArrayEq({
- actual: coll.find().toArray(),
- expected: [
- {_id: 2, a: {}},
- {_id: 3, b: 1},
- {_id: 4, a: "$notAFieldPath", c: "updated"},
- ],
- });
-}
-
-// Run delete commands with 'let' parameters containing expressions.
-{
- setupColl();
-
- assert.commandWorked(db.runCommand({
- delete: coll.getName(),
- deletes: [{
- q: {$expr: {$eq: ["$a", "$$c"]}},
- limit: 0, // multi
- }],
- let : {c: missingLetParam}
- }));
- assertArrayEq({
- actual: coll.find().toArray(),
- expected: [{_id: 2, a: {}}, {_id: 4, a: "$notAFieldPath"}],
- });
-
- // Undo changes.
- setupColl();
-
- assert.commandWorked(db.runCommand({
- delete: coll.getName(),
- deletes: [{
- q: {$expr: {$eq: ["$a", "$$c"]}},
- limit: 0, // multi
- }],
- let : {c: literalLetParam}
- }));
- assertArrayEq({
- actual: coll.find().toArray(),
- expected: [{_id: 2, a: {}}, {_id: 3, b: 1}],
- });
-}
-
-// Run a $lookup with let/pipeline syntax. In sharded environments, this will require serializing
-// 'let' variables to send to the shards. One of the documents in the collection is missing the
-// local field ("$a"), which will cause a missing 'let' variable to be serialized.
-{
- setupColl();
-
- const result = coll.aggregate([
- {
- $lookup: {
- from: coll.getName(),
- as: "res",
- let: {local_a: "$a"},
- pipeline: [{$match: {$expr: {$eq: ["$$local_a", "$a"]},}}, {$project: {_id: 1}}]
- }
- }
- ]).toArray();
- assertArrayEq({
- actual: result,
- expected: [
- {_id: 2, a: {}, res: [{_id: 2}]},
- {_id: 3, b: 1, res: [{_id: 3}]},
- {_id: 4, a: "$notAFieldPath", res: [{_id: 4}]},
- ],
- });
-}
-}());
diff --git a/jstests/core/commands_namespace_parsing.js b/jstests/core/commands_namespace_parsing.js
index c6745daefce..6016eaa4fee 100644
--- a/jstests/core/commands_namespace_parsing.js
+++ b/jstests/core/commands_namespace_parsing.js
@@ -10,7 +10,6 @@
// uses_testing_only_commands,
// uses_map_reduce_with_temp_collections,
// no_selinux,
-// uses_compact,
// ]
// This file tests that commands namespace parsing rejects embedded null bytes.
diff --git a/jstests/core/compact_keeps_indexes.js b/jstests/core/compact_keeps_indexes.js
index ad1c5825306..f4f59165272 100644
--- a/jstests/core/compact_keeps_indexes.js
+++ b/jstests/core/compact_keeps_indexes.js
@@ -4,7 +4,6 @@
// @tags: [
// # compact command is not available on embedded
// incompatible_with_embedded,
-// uses_compact,
// uses_multiple_connections,
// uses_parallel_shell,
// ]
diff --git a/jstests/core/connection_string_validation.js b/jstests/core/connection_string_validation.js
index 6236e445a77..302a42d61dc 100644
--- a/jstests/core/connection_string_validation.js
+++ b/jstests/core/connection_string_validation.js
@@ -1,7 +1,6 @@
// Test validation of connection strings passed to the JavaScript "connect()" function.
// @tags: [
// uses_multiple_connections,
-// docker_incompatible,
// ]
// Related to SERVER-8030.
diff --git a/jstests/core/cover_null_queries.js b/jstests/core/cover_null_queries.js
index 1ff45ea7b78..50bf0b58b07 100644
--- a/jstests/core/cover_null_queries.js
+++ b/jstests/core/cover_null_queries.js
@@ -3,9 +3,7 @@
* @tags: [
* assumes_unsharded_collection,
* requires_non_retryable_writes,
- * requires_fcv_60,
- * # This test could produce unexpected explain output if additional indexes are created.
- * assumes_no_implicit_index_creation,
+ * requires_fcv_52
* ]
*/
(function() {
@@ -13,7 +11,6 @@
load("jstests/aggregation/extras/utils.js"); // For arrayEq().
load("jstests/libs/analyze_plan.js"); // For getAggPlanStages() and getPlanStages().
-load("jstests/libs/clustered_collections/clustered_collection_util.js");
const coll = db.cover_null_queries;
coll.drop();
@@ -60,22 +57,12 @@ function validateStages({cmdObj, expectedStages, isAgg}) {
*/
function validateFindCmdOutputAndPlan({filter, projection, expectedStages, expectedOutput}) {
const cmdObj = {find: coll.getName(), filter: filter, projection: projection};
-
- // Compare index output with expected output.
if (expectedOutput) {
const res = assert.commandWorked(coll.runCommand(cmdObj));
const ouputArray = new DBCommandCursor(coll.getDB(), res).toArray();
assert(arrayEq(expectedOutput, ouputArray), ouputArray);
}
-
- // Validate explain.
validateStages({cmdObj, expectedStages});
-
- // Verify that we get the same output as we expect without an index.
- const noIndexCmdObj = Object.assign(cmdObj, {hint: {$natural: 1}});
- const resNoIndex = assert.commandWorked(coll.runCommand(noIndexCmdObj));
- const noIndexOutArr = new DBCommandCursor(coll.getDB(), resNoIndex).toArray();
- assert(arrayEq(expectedOutput, noIndexOutArr), noIndexOutArr);
}
/**
@@ -84,18 +71,10 @@ function validateFindCmdOutputAndPlan({filter, projection, expectedStages, expec
* are present in the plan returned.
*/
function validateSimpleCountCmdOutputAndPlan({filter, expectedStages, expectedCount}) {
- // Compare index output with expected output.
const cmdObj = {count: coll.getName(), query: filter};
const res = assert.commandWorked(coll.runCommand(cmdObj));
assert.eq(res.n, expectedCount);
-
- // Validate explain.
validateStages({cmdObj, expectedStages});
-
- // Verify that we get the same output with and without an index.
- const noIndexCmdObj = Object.assign(cmdObj, {hint: {$natural: 1}});
- const resNoIndex = assert.commandWorked(coll.runCommand(noIndexCmdObj));
- assert.eq(resNoIndex.n, expectedCount);
}
/**
@@ -109,42 +88,11 @@ function validateCountAggCmdOutputAndPlan({filter, expectedStages, expectedCount
pipeline: pipeline || [{$match: filter}, {$count: "count"}],
cursor: {},
};
-
- // Compare index output with expected output.
const cmdRes = assert.commandWorked(coll.runCommand(cmdObj));
const countRes = cmdRes.cursor.firstBatch;
assert.eq(countRes.length, 1, cmdRes);
assert.eq(countRes[0].count, expectedCount, countRes);
-
- // Validate explain.
validateStages({cmdObj, expectedStages, isAgg: true});
-
- // Verify that we get the same output as we expect without an index.
- const noIndexCmdObj = Object.assign(cmdObj, {hint: {$natural: 1}});
- const resNoIndex = assert.commandWorked(coll.runCommand(noIndexCmdObj));
- const countResNoIndex = resNoIndex.cursor.firstBatch;
- assert.eq(countResNoIndex.length, 1, cmdRes);
- assert.eq(countResNoIndex[0].count, expectedCount, countRes);
-}
-
-/**
- * Same as above, but uses a $group count.
- */
-function validateGroupCountAggCmdOutputAndPlan({filter, expectedStages, expectedCount}) {
- validateCountAggCmdOutputAndPlan({
- expectedStages,
- expectedCount,
- pipeline: [{$match: filter}, {$group: {_id: 0, count: {$count: {}}}}]
- });
-}
-
-function getExpectedStagesIndexScanAndFetch(extraStages) {
- const clustered = ClusteredCollectionUtil.areAllCollectionsClustered(db.getMongo());
- const result = clustered ? {"CLUSTERED_IXSCAN": 1} : {"FETCH": 1, "IXSCAN": 1};
- for (const stage in extraStages) {
- result[stage] = extraStages[stage];
- }
- return result;
}
assert.commandWorked(coll.createIndex({a: 1, _id: 1}));
@@ -204,7 +152,7 @@ validateFindCmdOutputAndPlan({
expectedStages: {"IXSCAN": 1, "FETCH": 0, "PROJECTION_COVERED": 1},
});
-// We can cover a $in with null and an empty array predicate.
+// Same as above, but special case for null and empty array predicate.
validateFindCmdOutputAndPlan({
filter: {a: {$in: [null, []]}},
projection: {_id: 1},
@@ -217,21 +165,6 @@ validateSimpleCountCmdOutputAndPlan({
expectedStages: {"IXSCAN": 1, "FETCH": 0},
});
-// We cannot cover a $in with null and an array predicate.
-// TODO SERVER-71058: It should be possible to cover this case and the more general case of matching
-// an array on a non-multikey index.
-validateFindCmdOutputAndPlan({
- filter: {a: {$in: [null, ["a"]]}},
- projection: {_id: 1},
- expectedOutput: [{_id: 3}, {_id: 4}, {_id: 6}, {_id: 7}],
- expectedStages: {"IXSCAN": 1, "FETCH": 1, "PROJECTION_SIMPLE": 1},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {a: {$in: [null, ["a"]]}},
- expectedCount: 4,
- expectedStages: {"IXSCAN": 1, "FETCH": 1, "COUNT": 1},
-});
-
// Verify that a more complex projection that only relies on the _id field does not need a FETCH.
validateFindCmdOutputAndPlan({
filter: {a: null},
@@ -339,18 +272,18 @@ validateFindCmdOutputAndPlan({
validateSimpleCountCmdOutputAndPlan({
filter: {a: null, _id: 3},
expectedCount: 1,
- expectedStages: getExpectedStagesIndexScanAndFetch({"OR": 0, "COUNT_SCAN": 0}),
+ expectedStages: {"FETCH": 1, "IXSCAN": 1, "OR": 0, "COUNT_SCAN": 0}
});
validateCountAggCmdOutputAndPlan({
filter: {a: null, _id: 3},
expectedCount: 1,
- expectedStages: getExpectedStagesIndexScanAndFetch({"OR": 0, "COUNT_SCAN": 0}),
+ expectedStages: {"FETCH": 1, "IXSCAN": 1, "OR": 0, "COUNT_SCAN": 0},
});
validateFindCmdOutputAndPlan({
filter: {a: null, _id: 3},
projection: {_id: 1},
expectedOutput: [{_id: 3}],
- expectedStages: getExpectedStagesIndexScanAndFetch({"PROJECTION_SIMPLE": 1}),
+ expectedStages: {"IXSCAN": 1, "FETCH": 1, "PROJECTION_SIMPLE": 1},
});
// Verify that if the index is multikey and the query searches for null and empty array values, then
@@ -758,265 +691,4 @@ validateCountAggCmdOutputAndPlan({
expectedCount: 4,
expectedStages: {"OR": 1, "COUNT_SCAN": 2, "IXSCAN": 0, "FETCH": 0},
});
-
-// Validate that we can use the optimization when we have regex without array elements in a $in or
-// $or. See SERVER-70436 for more details.
-coll.drop();
-
-assert.commandWorked(coll.insertMany([
- {_id: 1, a: '123456'},
- {_id: 2, a: '1234567'},
- {_id: 3, a: ' 12345678'},
- {_id: 4, a: '444456'},
- {_id: 5, a: ''},
- {_id: 6, a: null},
- {_id: 7},
-]));
-
-assert.commandWorked(coll.createIndex({a: 1, _id: 1}));
-
-// TODO SERVER-70998: Can apply optimization in case without regex; however, we still can't use a
-// COUNT_SCAN in this case.
-validateFindCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: ""}]},
- projection: {_id: 1},
- expectedOutput: [{_id: 5}, {_id: 6}, {_id: 7}],
- expectedStages: {"IXSCAN": 1, "FETCH": 0, "PROJECTION_COVERED": 1},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: ""}]},
- expectedCount: 3,
- expectedStages: {"COUNT": 1, "IXSCAN": 1, "FETCH": 0},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: ""}]},
- expectedCount: 3,
- expectedStages: {"IXSCAN": 1, "FETCH": 0},
-});
-
-// Can still apply optimization when we have regex.
-validateFindCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: {$regex: "^$"}}]},
- projection: {_id: 1},
- expectedOutput: [{_id: 5}, {_id: 6}, {_id: 7}],
- expectedStages: {"IXSCAN": 1, "FETCH": 0, "PROJECTION_COVERED": 1},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: {$regex: "^$"}}]},
- expectedCount: 3,
- expectedStages: {"IXSCAN": 1, "FETCH": 0, "COUNT": 1},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: {$regex: "^$"}}]},
- expectedCount: 3,
- expectedStages: {"IXSCAN": 1, "FETCH": 0},
-});
-
-// Now test case with a multikey index. We can't leverage the optimization here.
-assert.commandWorked(coll.insert({_id: 8, a: [1, 2, 3]}));
-assert.commandWorked(coll.insert({_id: 9, a: []}));
-
-validateFindCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: []}, {a: {$regex: "^$"}}]},
- projection: {_id: 1},
- expectedOutput: [{_id: 5}, {_id: 6}, {_id: 7}, {_id: 9}],
- expectedStages: {"IXSCAN": 1, "FETCH": 1, "PROJECTION_SIMPLE": 1},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: []}, {a: {$regex: "^$"}}]},
- expectedCount: 4,
- expectedStages: {"COUNT": 1, "IXSCAN": 1, "FETCH": 1},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: []}, {a: {$regex: "^$"}}]},
- expectedCount: 4,
- expectedStages: {"IXSCAN": 1, "FETCH": 1},
-});
-
-// We also shouldn't cover queries on multikey indexes where $in includes an array, as we will still
-// need a filter after the IXSCAN to correctly return
-validateFindCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: []}, {a: [2]}]},
- projection: {_id: 1},
- expectedOutput: [{_id: 6}, {_id: 7}, {_id: 9}],
- expectedStages: {"IXSCAN": 1, "FETCH": 1},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: []}, {a: [2]}]},
- expectedCount: 3,
- expectedStages: {"IXSCAN": 1, "FETCH": 1},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {$or: [{a: null}, {a: []}, {a: [2]}]},
- expectedCount: 3,
- expectedStages: {"IXSCAN": 1, "FETCH": 1},
-});
-
-// Validate that when we have a dotted path, we return the correct results for null queries.
-coll.drop();
-assert.commandWorked(coll.insertMany([
- {_id: 1, a: 1},
- {_id: 2, a: null},
- {_id: 3},
- {_id: 4, a: {b: 1}},
- {_id: 5, a: {b: null}},
- {_id: 6, a: {c: 1}},
-]));
-assert.commandWorked(coll.createIndex({"a.b": 1, _id: 1}));
-
-validateFindCmdOutputAndPlan({
- filter: {"a.b": null},
- projection: {_id: 1},
- expectedOutput: [{_id: 1}, {_id: 2}, {_id: 3}, {_id: 5}, {_id: 6}],
- expectedStages: {"IXSCAN": 1, "PROJECTION_COVERED": 1, "FETCH": 0},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {"a.b": null},
- expectedCount: 5,
- expectedStages: {"OR": 1, "COUNT_SCAN": 2, "IXSCAN": 0, "FETCH": 0},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {"a.b": null},
- expectedCount: 5,
- expectedStages: {"OR": 1, "COUNT_SCAN": 2, "IXSCAN": 0, "FETCH": 0},
-});
-
-validateFindCmdOutputAndPlan({
- filter: {a: {b: null}},
- projection: {_id: 1},
- expectedOutput: [{_id: 5}],
- expectedStages: {"COLLSCAN": 1, "PROJECTION_SIMPLE": 1},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {a: {b: null}},
- expectedCount: 1,
- expectedStages: {"COLLSCAN": 1},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {a: {b: null}},
- expectedCount: 1,
- expectedStages: {"COLLSCAN": 1},
-});
-
-// Still need fetch if we don't have a sufficiently restrictive projection.
-validateFindCmdOutputAndPlan({
- filter: {"a.b": null},
- projection: {_id: 1, a: 1},
- expectedOutput: [
- {_id: 1, a: 1},
- {_id: 2, a: null},
- {_id: 3},
- {_id: 5, a: {b: null}},
- {_id: 6, a: {c: 1}},
- ],
- expectedStages: {"IXSCAN": 1, "FETCH": 1},
-});
-
-// Make index multikey, and test case where field b is nested in an array.
-assert.commandWorked(coll.insertMany([
- {_id: 7, a: [{b: null}]},
- {_id: 8, a: [{b: []}]},
- {_id: 9, a: [{b: [1, 2, 3]}]},
- {_id: 10, a: [{b: 123}]},
- {_id: 11, a: [{c: 123}]},
- {_id: 12, a: []},
- {_id: 13, a: [{}]},
- {_id: 14, a: [1, 2, 3]},
- {_id: 15, a: [{b: 1}, {c: 2}, {b: 3}]},
- {_id: 16, a: [null]},
-]));
-
-validateFindCmdOutputAndPlan({
- filter: {"a.b": null},
- projection: {_id: 1},
- expectedOutput: [
- {_id: 1},
- {_id: 2},
- {_id: 3},
- {_id: 5},
- {_id: 6},
- {_id: 7},
- {_id: 11},
- {_id: 13},
- {_id: 15}
- ],
- expectedStages: {"IXSCAN": 1, "PROJECTION_SIMPLE": 1, "FETCH": 1},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {"a.b": null},
- expectedCount: 9,
- expectedStages: {"COUNT": 1, "IXSCAN": 1, "FETCH": 1},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {"a.b": null},
- expectedCount: 9,
- expectedStages: {"IXSCAN": 1, "FETCH": 1},
-});
-
-validateFindCmdOutputAndPlan({
- filter: {a: {b: null}},
- projection: {_id: 1},
- expectedOutput: [{_id: 5}, {_id: 7}],
- expectedStages: {
- "COLLSCAN": 1,
- "PROJECTION_SIMPLE": 1,
- },
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {a: {b: null}},
- expectedCount: 2,
- expectedStages: {"COLLSCAN": 1},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {a: {b: null}},
- expectedCount: 2,
- expectedStages: {"COLLSCAN": 1},
-});
-
-validateFindCmdOutputAndPlan({
- filter: {a: [{b: null}]},
- projection: {_id: 1},
- expectedOutput: [{_id: 7}],
- expectedStages: {"COLLSCAN": 1, "PROJECTION_SIMPLE": 1},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {a: [{b: null}]},
- expectedCount: 1,
- expectedStages: {"COLLSCAN": 1},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {a: [{b: null}]},
- expectedCount: 1,
- expectedStages: {"COLLSCAN": 1},
-});
-
-// We still need a FETCH for composite paths, because both {a: [1,2,3]} and {"a.b": null} generate
-// null index keys, but the former should not match the predicate below.
-validateFindCmdOutputAndPlan({
- filter: {"a.b": {$in: [null, []]}},
- projection: {_id: 1},
- expectedOutput: [
- {_id: 1},
- {_id: 2},
- {_id: 3},
- {_id: 5},
- {_id: 6},
- {_id: 7},
- {_id: 8},
- {_id: 11},
- {_id: 13},
- {_id: 15}
- ],
- expectedStages: {"IXSCAN": 1, "PROJECTION_SIMPLE": 1, "FETCH": 1},
-});
-validateSimpleCountCmdOutputAndPlan({
- filter: {"a.b": {$in: [null, []]}},
- expectedCount: 10,
- expectedStages: {"IXSCAN": 1, "FETCH": 1},
-});
-validateGroupCountAggCmdOutputAndPlan({
- filter: {"a.b": {$in: [null, []]}},
- expectedCount: 10,
- expectedStages: {"IXSCAN": 1, "FETCH": 1},
-});
})();
diff --git a/jstests/core/create_indexes.js b/jstests/core/create_indexes.js
index afa9db6a93b..bdb0561094a 100644
--- a/jstests/core/create_indexes.js
+++ b/jstests/core/create_indexes.js
@@ -178,10 +178,4 @@ var configDB = db.getSiblingDB('config');
res =
configDB.runCommand({createIndexes: 'transactions', indexes: [{key: {star: 1}, name: 'star'}]});
assert.commandFailedWithCode(res, ErrorCodes.IllegalOperation);
-
-// Test that providing an empty list of index spec for config.transactions should also fail with
-// IllegalOperation, rather than BadValue for a normal collection.
-// This is consistent with server behavior prior to 6.0.
-res = configDB.runCommand({createIndexes: 'transactions', indexes: []});
-assert.commandFailedWithCode(res, ErrorCodes.IllegalOperation);
}());
diff --git a/jstests/core/currentop_cursors.js b/jstests/core/currentop_cursors.js
index 483d2d3eb62..65baff3363f 100644
--- a/jstests/core/currentop_cursors.js
+++ b/jstests/core/currentop_cursors.js
@@ -9,7 +9,6 @@
* no_selinux,
* # This test contains assertions for the hostname that operations run on.
* tenant_migration_incompatible,
- * docker_incompatible,
* ]
*/
diff --git a/jstests/core/currentop_shell.js b/jstests/core/currentop_shell.js
index 5dbbe958dc7..c96ef2507f1 100644
--- a/jstests/core/currentop_shell.js
+++ b/jstests/core/currentop_shell.js
@@ -11,8 +11,6 @@
* # currentOp results.
* assumes_read_preference_unchanged,
* no_selinux,
- * # Uses $function operator.
- * requires_scripting,
* ]
*/
diff --git a/jstests/core/currentop_waiting_for_latch.js b/jstests/core/currentop_waiting_for_latch.js
index 1efc4deebc5..c8a18d57d84 100644
--- a/jstests/core/currentop_waiting_for_latch.js
+++ b/jstests/core/currentop_waiting_for_latch.js
@@ -2,8 +2,7 @@
* Tests that a backtrace will appear in the $currentOp output if the backtrace option is
* set to true and there is a latch timeout.
*
- * @tags: [assumes_read_concern_unchanged, assumes_read_preference_unchanged, no_selinux,
- * requires_latch_analyzer, multiversion_incompatible]
+ * @tags: [assumes_read_concern_unchanged, assumes_read_preference_unchanged, no_selinux]
*/
(function() {
"use strict";
diff --git a/jstests/core/doc_validation_with_now_variable.js b/jstests/core/doc_validation_with_now_variable.js
deleted file mode 100644
index ccb00fffd41..00000000000
--- a/jstests/core/doc_validation_with_now_variable.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Tests that insertion with a $$NOW Validator works properly.
- *
- * @tags: [assumes_no_implicit_collection_creation_after_drop]
- */
-(function() {
-"use strict";
-const coll = db.coll_doc_validation_with_now_variable;
-coll.drop();
-// assert.commandWorked(db.createCollection("coll_doc_validation_with_now_variable",
-// {validator: {"$expr": {$gt: ["$ts", "$$NOW"]}}}));
-
-assert.commandWorked(db.createCollection("coll_doc_validation_with_now_variable",
- {validator: {"$expr": {$lt: ["$ts", "$$NOW"]}}}));
-
-assert.commandWorked(coll.insert({"ts": new Date(1589617694938)}));
-
-const result = coll.insert({"ts": new Date(2708791380000)});
-assert.commandFailedWithCode(result, ErrorCodes.DocumentValidationFailure, tojson(result));
-})();
diff --git a/jstests/core/elemmatch_or_pushdown_paths.js b/jstests/core/elemmatch_or_pushdown_paths.js
deleted file mode 100644
index 18e06063674..00000000000
--- a/jstests/core/elemmatch_or_pushdown_paths.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Test OR-pushdown fixes for elemMatch based on SERVER-74954.
- */
-(function() {
-"use strict";
-
-load("jstests/aggregation/extras/utils.js"); // for "arrayEq".
-load('jstests/libs/analyze_plan.js'); // for "planHasStage".
-
-const coll = db.jstests_elemmatch_or_pushdown_paths;
-
-coll.drop();
-
-assert.commandWorked(coll.insert([
- {a: 1, b: [{c: 1}]},
- {a: 2, b: [{c: 1}]},
- {a: 3, b: [{c: 1}]},
- {a: 4, b: [{c: 1}]},
-]));
-assert.commandWorked(coll.createIndex({"b.c": 1, a: 1}));
-
-// Test exact bounds.
-assert(arrayEq(coll.find({
- $and: [
- {$or: [{a: {$lt: 2}}, {a: {$gt: 3}}]},
- {b: {$elemMatch: {c: {$eq: 1, $exists: true}}}}
- ]
- },
- {_id: 0})
- .hint({"b.c": 1, a: 1})
- .toArray(),
- [
- {a: 1, b: [{c: 1}]},
- {a: 4, b: [{c: 1}]},
- ]));
-
-// Similar test, but use $mod instead of $exists.
-const results = coll.find({
- $and: [
- {$or: [{a: {$lt: 2}}, {a: {$gt: 3}}]},
- {b: {$elemMatch: {c: {$eq: 1, $mod: [2, 1]}}}}
- ]
- },
- {_id: 0})
- .toArray();
-
-assert(arrayEq(results,
- [
- {a: 1, b: [{c: 1}]},
- {a: 4, b: [{c: 1}]},
- ]),
- results);
-
-assert(coll.drop());
-assert.commandWorked(coll.insert([
- {a: 5, b: [{c: 5, d: 6, e: 7}]},
- {a: 5, b: [{c: 5, d: 6, e: 8}]},
- {a: 5, b: [{c: 5, d: 5, e: 7}]},
- {a: 4, b: [{c: 5, d: 6, e: 7}]},
-]));
-assert.commandWorked(coll.createIndex({"b.d": 1, "b.c": 1}));
-assert.commandWorked(coll.createIndex({"b.e": 1, "b.c": 1}));
-
-// Test OR within elemmatch.
-assert(arrayEq(
- coll.find({$and: [{a: 5}, {b: {$elemMatch: {$and: [{c: 5}, {$or: [{d: 6}, {e: 7}]}]}}}]},
- {_id: 0})
- .toArray(),
- [
- {a: 5, b: [{c: 5, d: 6, e: 7}]},
- {a: 5, b: [{c: 5, d: 6, e: 8}]},
- {a: 5, b: [{c: 5, d: 5, e: 7}]},
- ]));
-})();
diff --git a/jstests/core/empty_ts.js b/jstests/core/empty_ts.js
deleted file mode 100644
index 926de0fd790..00000000000
--- a/jstests/core/empty_ts.js
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * Test how inserts and updates behave with "Timestamp(0,0)" values.
- *
- * @tags: [
- * requires_fcv_60,
- * ]
- */
-(function() {
-"use strict";
-
-const coll = db.jstests_core_empty_ts;
-const emptyTs = Timestamp(0, 0);
-
-coll.drop();
-
-// Insert several documents. For the first document inserted (_id=101), the empty timestamp value
-// in field "a" should get replaced with the current timestamp.
-assert.commandWorked(coll.insert({_id: 101, a: emptyTs}));
-assert.commandWorked(coll.insert({_id: 102, a: 1}));
-assert.commandWorked(coll.insert({_id: 103, a: 2}));
-assert.commandWorked(coll.insert({_id: 106, a: 3}));
-assert.commandWorked(coll.insert({_id: 107, a: 4}));
-assert.commandWorked(coll.insert({_id: 108, a: 5}));
-assert.commandWorked(coll.insert({_id: 109, a: 6}));
-assert.commandWorked(coll.insert({_id: 110, a: 7}));
-assert.commandWorked(coll.insert({_id: 111, a: 8}));
-
-// Use a replacement-style update to update _id=102. This should result in field "a" being set to
-// the current timestamp.
-//
-// This is an example of how the special "empty timestamp" behavior works with a replacement-style
-// update.
-assert.commandWorked(coll.update({_id: 102}, {a: emptyTs}));
-
-// Use a replacement-style findAndModify to update _id=103. This should result in field "a" being
-// set to the current timestamp.
-let findAndModifyResult = coll.findAndModify({query: {_id: 103}, update: {a: emptyTs}});
-assert.eq(findAndModifyResult, {_id: 103, a: 2});
-
-// Do a replacement-style update to add a new document with _id=104. This should result in field "a"
-// being set to the current timestamp.
-assert.commandWorked(coll.update({_id: 104}, {a: emptyTs}, {upsert: true}));
-
-// Do a replacement-style findAndModify to add a new document with _id=105. This should result in
-// field "a" being set to the current timestamp.
-findAndModifyResult = coll.findAndModify({query: {_id: 105}, update: {a: emptyTs}, upsert: true});
-assert.eq(findAndModifyResult, null);
-
-// For the rest of the commands below, the empty timestamp values stored in field "a" should be
-// preserved as-is.
-
-// Do an update-operator-style update to update _id=106.
-assert.commandWorked(coll.update({_id: 106}, {$set: {a: emptyTs}}));
-
-// Do an update-operator-style findAndModify to update _id=107.
-findAndModifyResult = coll.findAndModify({query: {_id: 107}, update: {$set: {a: emptyTs}}});
-assert.eq(findAndModifyResult, {_id: 107, a: 4});
-
-// Do a pipeline-style update to update _id=108.
-assert.commandWorked(coll.update({_id: 108}, [{$addFields: {a: emptyTs}}]));
-
-// Do a pipeline-style findAndModify to update _id=109.
-findAndModifyResult = coll.findAndModify({query: {_id: 109}, update: [{$addFields: {a: emptyTs}}]});
-assert.eq(findAndModifyResult, {_id: 109, a: 6});
-
-// Do a pipeline-style update with $internalApplyOplogUpdate to update _id=110.
-assert.commandWorked(coll.update(
- {_id: 110}, [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}]));
-
-// Do a pipeline-style findAndModify with $internalApplyOplogUpdate to update _id=111.
-findAndModifyResult = coll.findAndModify({
- query: {_id: 111},
- update: [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}]
-});
-assert.eq(findAndModifyResult, {_id: 111, a: 8});
-
-// Do an update-operator-style update to add a new document with _id=112.
-assert.commandWorked(coll.update({_id: 112}, {$set: {a: emptyTs}}, {upsert: true}));
-
-// Do an update-operator-style findAndModify to add a new document with _id=113.
-findAndModifyResult =
- coll.findAndModify({query: {_id: 113}, update: {$set: {a: emptyTs}}, upsert: true});
-assert.eq(findAndModifyResult, null);
-
-// Do a pipeline-style update to add a new document with _id=114.
-assert.commandWorked(coll.update({_id: 114}, [{$addFields: {a: emptyTs}}], {upsert: true}));
-
-// Do a pipeline-style findAndModify to add a new document with _id=115.
-findAndModifyResult =
- coll.findAndModify({query: {_id: 115}, update: [{$addFields: {a: emptyTs}}], upsert: true});
-assert.eq(findAndModifyResult, null);
-
-// Do a pipline-style update with $internalApplyOplogUpdate to add a new document _id=116.
-assert.commandWorked(
- coll.update({_id: 116},
- [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}],
- {upsert: true}));
-
-// Do pipeline-style findAndModify with $internalApplyOplogUpdate to add a new document _id=117.
-findAndModifyResult = coll.findAndModify({
- query: {_id: 117},
- update: [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}],
- upsert: true
-});
-assert.eq(findAndModifyResult, null);
-
-// Verify that all the insert, update, and findAndModify commands behaved the way we expected.
-for (let i = 101; i <= 117; ++i) {
- let result = coll.findOne({_id: i});
-
- if (i >= 106) {
- assert.eq(tojson(result.a), tojson(emptyTs), "_id=" + i);
- } else {
- assert.neq(tojson(result.a), tojson(emptyTs), "_id=" + i);
- }
-}
-
-// Insert a document with _id=Timestamp(0,0).
-assert.commandWorked(coll.insert({_id: emptyTs, a: 9}));
-
-// Verify the document we just inserted can be retrieved using the filter "{_id: Timestamp(0,0)}".
-let result = coll.findOne({_id: emptyTs});
-assert.eq(tojson(result._id), tojson(emptyTs), "_id=" + tojson(emptyTs));
-assert.eq(tojson(result.a), tojson(9), "_id=" + tojson(emptyTs));
-
-// Do a replacement-style update on the document.
-assert.commandWorked(coll.update({_id: emptyTs}, {_id: emptyTs, a: emptyTs}));
-
-// Verify the document we just updated can still be retrieved using "{_id: Timestamp(0,0)}", and
-// verify that field "a" was set to the current timestamp.
-result = coll.findOne({_id: emptyTs});
-assert.eq(tojson(result._id), tojson(emptyTs), "_id=" + tojson(emptyTs));
-assert.neq(tojson(result.a), tojson(emptyTs), "_id=" + tojson(emptyTs));
-}());
diff --git a/jstests/core/exhaust.js b/jstests/core/exhaust.js
index 202de9e4374..197b99fcaee 100644
--- a/jstests/core/exhaust.js
+++ b/jstests/core/exhaust.js
@@ -3,7 +3,6 @@
// # This test uses exhaust which does not use runCommand (required by the inject_tenant_prefix.js
// # override).
// tenant_migration_incompatible,
-// no_selinux
// ]
(function() {
diff --git a/jstests/core/explain5.js b/jstests/core/explain5.js
index 534aaf9665b..871a5f10d76 100644
--- a/jstests/core/explain5.js
+++ b/jstests/core/explain5.js
@@ -2,7 +2,7 @@
// @tags: [
// assumes_balancer_off,
// assumes_read_concern_local,
-// operations_longer_than_stepdown_interval, # large bulk inserts
+// operations_longer_than_stepdown_interval, // large bulk inserts
// ]
(function() {
diff --git a/jstests/core/explain_agg_write_concern.js b/jstests/core/explain_agg_write_concern.js
index ec246140abe..9ff556489fa 100644
--- a/jstests/core/explain_agg_write_concern.js
+++ b/jstests/core/explain_agg_write_concern.js
@@ -5,7 +5,6 @@
// assumes_unsharded_collection,
// assumes_write_concern_unchanged,
// does_not_support_stepdowns,
-// references_foreign_collection,
// requires_non_retryable_commands,
// ]
diff --git a/jstests/core/explain_skip.js b/jstests/core/explain_skip.js
deleted file mode 100644
index b6e01d6a436..00000000000
--- a/jstests/core/explain_skip.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Tests that explain reports the skip stage statistics correctly.
- *
- * @tags: [
- * assumes_unsharded_collection,
- * assumes_against_mongod_not_mongos,
- * ]
- */
-load("jstests/libs/analyze_plan.js"); // For getWinningPlan.
-
-var coll = db.explain_skip;
-coll.drop();
-
-assert.commandWorked(coll.insert({a: 1, b: 1}));
-assert.commandWorked(coll.insert({a: 1, b: 2}));
-assert.commandWorked(coll.insert({a: 1, b: 3}));
-assert.commandWorked(coll.insert({a: 2, b: 1}));
-assert.commandWorked(coll.insert({a: 2, b: 2}));
-assert.commandWorked(coll.insert({a: 2, b: 3}));
-
-assert.commandWorked(coll.createIndex({a: 1}));
-assert.commandWorked(coll.createIndex({b: 1}));
-
-var explain = coll.find({a: 1, b: 1}).sort({_id: 1}).skip(5).explain();
-var winningPlan = getWinningPlan(explain.queryPlanner);
-var skipStage = getPlanStage(winningPlan, "SKIP");
-assert.neq(null, skipStage, explain);
-assert.eq(5, skipStage.skipAmount, explain);
diff --git a/jstests/core/expr_index_use.js b/jstests/core/expr_index_use.js
index 488c9267e90..95a5699eb48 100644
--- a/jstests/core/expr_index_use.js
+++ b/jstests/core/expr_index_use.js
@@ -279,6 +279,11 @@ confirmExpectedExprExecution({$eq: ["$w", NaN]}, {nReturned: 1, expectedIndex: {
confirmExpectedExprExecution({$eq: ["$w", undefined]}, {nReturned: 16});
confirmExpectedExprExecution({$eq: ["$w", "$$REMOVE"]}, {nReturned: 16});
+// Test that equality to null queries can use a sparse index.
+assert.commandWorked(coll.dropIndex({w: "hashed"}));
+assert.commandWorked(coll.createIndex({w: 1}, {sparse: true}));
+confirmExpectedExprExecution({$eq: ["$w", null]}, {nReturned: 1, expectedIndex: {w: 1}});
+
// Equality match against text index prefix is expected to fail. Equality predicates are
// required against the prefix fields of a text index, but currently $eq inside $expr does not
// qualify.
diff --git a/jstests/core/field_name_validation.js b/jstests/core/field_name_validation.js
index 42d0d5cf21d..7dd249f98b2 100644
--- a/jstests/core/field_name_validation.js
+++ b/jstests/core/field_name_validation.js
@@ -66,9 +66,6 @@ assert.commandWorked(coll.insert({_id: 2, $valid: 1, $db: 1}));
assert.commandWorked(coll.insert({_id: 3, $valid: 1, $ref: 1}));
assert.commandWorked(coll.insert({_id: 4, $valid: 1, $alsoValid: 1}));
-// Valid, because _id.$gt is a field name, and not equivalent to {_id: {$gt: 4}}
-assert.commandWorked(coll.insert({"_id.$gt": 4}));
-
//
// Update command field name validation.
//
@@ -96,16 +93,9 @@ assert.writeErrorWithCode(coll.update({"a.b": 1}, {_id: {$invalid: 1}}, {upsert:
ErrorCodes.DollarPrefixedFieldName);
assert.writeErrorWithCode(coll.update({"a.b": 1}, {$set: {_id: {$invalid: 1}}}, {upsert: true}),
ErrorCodes.DollarPrefixedFieldName);
-assert.writeErrorWithCode(coll.update({"a.b": 1}, {$set: {"_id.$gt": 1}}, {upsert: true}),
- ErrorCodes.DollarPrefixedFieldName);
assert.writeErrorWithCode(
coll.update({"a.b": 1}, {$setOnInsert: {_id: {$invalid: 1}}}, {upsert: true}),
ErrorCodes.DollarPrefixedFieldName);
-assert.writeErrorWithCode(
- coll.update({"a.b": 1}, {$setOnInsert: {"_id.$invalid": 1}}, {upsert: true}),
- ErrorCodes.DollarPrefixedFieldName);
-assert.writeErrorWithCode(coll.update({"_id.$gt": 1}, {$set: {a: 1}}, {upsert: true}),
- ErrorCodes.DollarPrefixedFieldName);
// Replacement-style updates can contain nested $-prefixed fields.
assert.commandWorked(coll.update({"a.b": 1}, {a: {$c: 1}}));
diff --git a/jstests/core/find_with_resume_after_param.js b/jstests/core/find_with_resume_after_param.js
deleted file mode 100644
index 26717d063a4..00000000000
--- a/jstests/core/find_with_resume_after_param.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * Tests that the internal parameter "$_resumeAfter" validates the type of the 'recordId' for
- * clustered and non clustered collections.
- * @tags: [
- * # Queries on mongoS may not request or provide a resume token.
- * assumes_against_mongod_not_mongos,
- * requires_fcv_60,
- * sbe_incompatible,
- * ]
- */
-
-(function() {
-"use strict";
-
-load("jstests/libs/collection_drop_recreate.js"); // For assertDropCollection.
-load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-
-const clustered = db.clusteredColl;
-const nonClustered = db.normalColl;
-const clusteredName = clustered.getName();
-const nonClusteredName = nonClustered.getName();
-
-assertDropCollection(db, clusteredName);
-assertDropCollection(db, nonClusteredName);
-
-db.createCollection(clusteredName, {clusteredIndex: {key: {_id: 1}, unique: true}});
-db.createCollection(nonClusteredName);
-
-// Insert some documents.
-const docs = [{_id: 1, a: 1}, {_id: 2, a: 2}, {_id: 3, a: 3}];
-assert.commandWorked(clustered.insertMany(docs));
-assert.commandWorked(nonClustered.insertMany(docs));
-
-function validateFailedResumeAfter({collName, resumeAfterSpec, errorCode, explainFail}) {
- const spec = {
- find: collName,
- filter: {},
- $_requestResumeToken: true,
- $_resumeAfter: resumeAfterSpec,
- hint: {$natural: 1}
- };
- assert.commandFailedWithCode(db.runCommand(spec), errorCode);
- // Run the same query under an explain.
- if (explainFail) {
- assert.commandFailedWithCode(db.runCommand({explain: spec}), errorCode);
- } else {
- assert.commandWorked(db.runCommand({explain: spec}));
- }
-}
-
-// Confirm $_resumeAfter will fail for clustered collections if the recordId is Long.
-validateFailedResumeAfter({
- collName: clusteredName,
- resumeAfterSpec: {'$recordId': NumberLong(2)},
- errorCode: 7738600,
- explainFail: true
-});
-
-// Confirm $_resumeAfter will fail with 'KeyNotFound' if given a non existent recordId.
-validateFailedResumeAfter({
- collName: clusteredName,
- resumeAfterSpec: {'$recordId': BinData(5, '1234')},
- errorCode: ErrorCodes.KeyNotFound
-});
-
-// TODO SERVER-78103: Added test for $recordId:null
-
-// Confirm $_resumeAfter will fail for normal collections if it is of type BinData.
-validateFailedResumeAfter({
- collName: nonClusteredName,
- resumeAfterSpec: {'$recordId': BinData(5, '1234')},
- errorCode: 7738600,
- explainFail: true
-});
-
-// Confirm $_resumeAfter token will fail with 'KeyNotFound' if given a non existent recordId.
-validateFailedResumeAfter({
- collName: nonClusteredName,
- resumeAfterSpec: {'$recordId': NumberLong(8)},
- errorCode: ErrorCodes.KeyNotFound
-});
-
-// Confirm $_resumeAfter token will work with 'null'.
-assert.commandWorked(db.runCommand({
- find: nonClusteredName,
- filter: {},
- $_requestResumeToken: true,
- $_resumeAfter: {'$recordId': null},
- hint: {$natural: 1}
-}));
-
-// Confirm $_resumeAfter will fail to parse if collection does not exist.
-validateFailedResumeAfter({
- collName: "random",
- resumeAfterSpec: {'$recordId': null, "anotherField": null},
- errorCode: ErrorCodes.BadValue,
- explainFail: true
-});
-validateFailedResumeAfter({
- collName: "random",
- resumeAfterSpec: "string",
- errorCode: ErrorCodes.TypeMismatch,
- explainFail: true
-});
-}());
diff --git a/jstests/core/fts_index.js b/jstests/core/fts_index.js
index 0063440f39b..c78301509f1 100644
--- a/jstests/core/fts_index.js
+++ b/jstests/core/fts_index.js
@@ -78,17 +78,6 @@ assert.eq(0,
})
.length);
-// $-prefixed fields cannot be indexed.
-coll = db.getCollection(collNamePrefix + collCount++);
-coll.drop();
-assert.commandFailed(coll.createIndex({"a.$custom": "text"}, {name: indexName}));
-assert.eq(0,
- coll.getIndexes()
- .filter(function(z) {
- return z.name == indexName;
- })
- .length);
-
// SERVER-19519 Spec fails if '_fts' is specified on a non-text index.
coll = db.getCollection(collNamePrefix + collCount++);
coll.drop();
diff --git a/jstests/core/fts_index3.js b/jstests/core/fts_index3.js
index 62b9fe72e56..ac4730d0bd0 100644
--- a/jstests/core/fts_index3.js
+++ b/jstests/core/fts_index3.js
@@ -3,7 +3,6 @@
// key.
// @tags: [
// assumes_unsharded_collection,
-// requires_fcv_60,
// ]
// Test that updates to fields in a text-indexed document are correctly reflected in the text index.
@@ -111,11 +110,6 @@ assert.commandWorked(coll.update({}, {$set: {"a.language": "en"}}));
assert.eq(0, coll.find({$text: {$search: "testing", $language: "es"}}).itcount());
assert.eq(1, coll.find({$text: {$search: "testing", $language: "en"}}).itcount());
-// SERVER-78238: index with a dotted path should not index fields with a dot inside that make it
-// look like a dotted path.
-assert.commandWorked(coll.insert({"a.b": "ignored"}));
-assert.eq(0, coll.find({$text: {$search: "ignored"}}).itcount());
-
// 10) Same as #9, but with a wildcard text index.
coll = db.getCollection(collNamePrefix + collCount++);
coll.drop();
@@ -127,11 +121,6 @@ assert.commandWorked(coll.update({}, {$set: {"a.language": "en"}}));
assert.eq(0, coll.find({$text: {$search: "testing", $language: "es"}}).itcount());
assert.eq(1, coll.find({$text: {$search: "testing", $language: "en"}}).itcount());
-// SERVER-78238: index with a wildcard should not index fields with a dot inside or starting with $.
-assert.commandWorked(coll.insert({"a.b": "ignored"}));
-assert.commandWorked(coll.insert({"$personal": "ignored"}));
-assert.eq(0, coll.find({$text: {$search: "ignored"}}).itcount());
-
// 11) Create a text index on a single field with a custom language override, insert a document,
// update the language of the document (so as to change the stemming), and verify that $text with
// the new language returns the document.
diff --git a/jstests/core/fts_mix.js b/jstests/core/fts_mix.js
index f8bf850fb29..5942a85ec2c 100644
--- a/jstests/core/fts_mix.js
+++ b/jstests/core/fts_mix.js
@@ -1,3 +1,4 @@
+
(function() {
load("jstests/libs/fts.js");
load("jstests/aggregation/extras/utils.js"); // For resultsEq.
diff --git a/jstests/core/group_lookup_with_canonical_query_prefix.js b/jstests/core/group_lookup_with_canonical_query_prefix.js
deleted file mode 100644
index 408c336f771..00000000000
--- a/jstests/core/group_lookup_with_canonical_query_prefix.js
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * Tests that an aggregation pipeline with stages only allowed with 'trySbeEngine' runs correctly
- * when wrapped with a $group, or $lookup. This makes the query use SBE.
- * @tags: [
- * assumes_unsharded_collection,
- * assumes_against_mongod_not_mongos,
- * not_allowed_with_security_token,
- * does_not_support_causal_consistency,
- * # We modify the value of a query knob. setParameter is not persistent.
- * does_not_support_stepdowns,
- * tenant_migration_incompatible,
- * # Explain for the aggregate command cannot run within a multi-document transaction.
- * does_not_support_transactions,
- * # Explain command does not support read concerns other than local.
- * assumes_read_concern_local,
- * assumes_read_concern_unchanged,
- * requires_fcv_60,
- * no_selinux,
- * ]
- */
-load("jstests/aggregation/extras/utils.js"); // for arrayEq.
-load("jstests/libs/analyze_plan.js"); // for getEngine.
-
-function buildErrorString(found, expected) {
- return "Expected:\n" + tojson(expected) + "\nGot:\n" + tojson(found);
-}
-
-function makeExpectedDocs(lowerBound, upperBound, isProject = false) {
- let expectedDocsGroup = [];
- let expectedDocsLookup = [];
- for (let i = lowerBound; i < upperBound; i++) {
- expectedDocsGroup.push({_id: i});
- // We project on {x: 1} so 'y' will not be present in the result.
- if (isProject) {
- expectedDocsLookup.push({_id: i, x: i, xx: []});
- } else {
- expectedDocsLookup.push({_id: i, x: i, y: i, xx: []});
- }
- }
- return [expectedDocsGroup, expectedDocsLookup];
-}
-
-function runAndVerifyQuery(coll, pipeline, [expectedDocsGroup, expectedDocsLookup]) {
- // Run the query and explain.
- pipeline.push({$group: {_id: "$x"}});
- let res = coll.aggregate(pipeline);
- assert(arrayEq(res.toArray(), expectedDocsGroup),
- buildErrorString(res.toArray(), expectedDocsGroup));
- let explain = assert.commandWorked(coll.explain().aggregate(pipeline));
- assert.eq(getEngine(explain), "sbe", tojson(explain));
-
- pipeline.pop();
- pipeline.push({$lookup: {from: coll2Name, localField: "y", foreignField: "z", as: "xx"}});
- res = coll.aggregate(pipeline);
- assert(arrayEq(res.toArray(), expectedDocsLookup),
- buildErrorString(res.toArray(), expectedDocsLookup));
- explain = assert.commandWorked(coll.explain().aggregate(pipeline));
- assert.eq(getEngine(explain), "sbe", tojson(explain));
-}
-
-// Runs the query and verifies properties of the result and explain. If 'withIndex' is true, for
-// some queries, we use a distinct scan, which is only in the classic engine.
-function runQueries(coll, withIndex = false) {
- // $limit queries.
- runAndVerifyQuery(coll, [{$limit: 5}], makeExpectedDocs(0, 5));
-
- // $skip queries.
- runAndVerifyQuery(coll, [{$skip: 5}], makeExpectedDocs(5, 100));
-
- // $limit + $skip queries.
- runAndVerifyQuery(coll, [{$limit: 50}, {$skip: 10}], makeExpectedDocs(10, 50));
- runAndVerifyQuery(coll, [{$skip: 10}, {$limit: 5}], makeExpectedDocs(10, 15));
-
- // $sort + $limit + $skip queries.
- runAndVerifyQuery(coll, [{$sort: {x: 1}}, {$skip: 10}, {$limit: 20}], makeExpectedDocs(10, 30));
- runAndVerifyQuery(coll, [{$sort: {x: 1}}, {$limit: 40}, {$skip: 30}], makeExpectedDocs(30, 40));
-
- // Mixed queries.
- runAndVerifyQuery(
- coll,
- [{$match: {x: {$lte: 20}}}, {$sort: {x: 1}}, {$skip: 8}, {$limit: 5}, {$project: {x: 1}}],
- makeExpectedDocs(8, 13, true /*isProject*/));
-
- if (!withIndex) {
- // $sort queries.
- runAndVerifyQuery(coll, [{$sort: {x: 1}}], makeExpectedDocs(0, 100));
- runAndVerifyQuery(coll, [{$sort: {y: 1}}], makeExpectedDocs(0, 100));
-
- // $project queries.
- runAndVerifyQuery(coll, [{$project: {x: 1}}], makeExpectedDocs(0, 100, true /*isProject*/));
-
- // $match queries.
- runAndVerifyQuery(coll, [{$match: {x: 4}}], makeExpectedDocs(4, 5));
- }
-}
-
-function testIndexed(coll) {
- assert.commandWorked(coll.createIndex({x: 1}));
- assert.commandWorked(coll.createIndex({y: 1}));
- runQueries(coll, true /* withIndex */);
-}
-
-const collName = jsTestName();
-const coll2Name = jsTestName() + "2";
-let coll = db.getCollection(collName);
-let coll2 = db.getCollection(coll2Name);
-coll.drop();
-coll2.drop();
-
-let originalParamValue;
-try {
- originalParamValue = db.adminCommand({getParameter: 1, internalQueryForceClassicEngine: 1});
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false}));
-
- const docs = [];
- for (let i = 0; i < 100; i++) {
- docs.push({_id: i, x: i, y: i});
- }
-
- assert.commandWorked(coll.insertMany(docs));
- assert.commandWorked(coll2.insert({z: 100}));
- runQueries(coll);
- testIndexed(coll);
-} finally {
- assert.commandWorked(db.adminCommand({
- setParameter: 1,
- internalQueryForceClassicEngine: originalParamValue.internalQueryForceClassicEngine
- }));
-}
diff --git a/jstests/core/hostinfo.js b/jstests/core/hostinfo.js
index c3a0f34994a..04f341a659d 100644
--- a/jstests/core/hostinfo.js
+++ b/jstests/core/hostinfo.js
@@ -35,12 +35,8 @@ if (hostinfo.os.type != "") {
assert.neq(hostinfo.system.cpuAddrSize, "" || null || 0, "Missing CPU Address Size");
assert.neq(hostinfo.system.memSizeMB, "" || null, "Missing Memory Size");
assert.neq(hostinfo.system.numCores, "" || null || 0, "Missing Number of Cores");
- assert.neq(
- hostinfo.system.numPhysicalCores, "" || null || 0, "Missing Number of Physical Cores");
- assert.neq(hostinfo.system.numCpuSockets, "" || null || 0, "Missing Number of CPU Sockets");
assert.neq(hostinfo.system.cpuArch, "" || null, "Missing CPU Architecture");
assert.neq(hostinfo.system.numaEnabled, "" || null, "Missing NUMA flag");
- assert.neq(hostinfo.system.numNumaNodes, "" || null || 0, "Missing Number of NUMA Nodes");
}
var buildInfo = assert.commandWorked(db.runCommand({buildInfo: 1}));
diff --git a/jstests/core/index/sparse_index_internal_expr.js b/jstests/core/index/sparse_index_internal_expr.js
deleted file mode 100644
index 28bcb7db77f..00000000000
--- a/jstests/core/index/sparse_index_internal_expr.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Tests that a sparse index cannot be used to answer a $expr query unless the sparse index is
- * explicitly hinted. If a sparse index is hinted to answer a $expr query, incomplete results could
- * be returned.
- *
- * @tags: [
- * multiversion_incompatible,
- * does_not_support_transactions,
- * ]
- */
-
-(function() {
-"use strict";
-
-load("jstests/libs/analyze_plan.js");
-
-const coll = db.sparse_index_internal_expr;
-coll.drop();
-
-coll.insert({a: 1});
-
-const exprQuery = {
- $expr: {$lt: ["$missing", "r"]}
-};
-
-// Run a query with $expr on a missing field. This query will use a COLLSCAN plan and return
-// document '{a: 1}' because $expr expression does not apply type bracketing, specifically, the
-// missing field is evaluated to 'null'. The expression returns "true" because 'null' < "r".
-let res = coll.find(exprQuery, {_id: 0}).toArray();
-
-assert.eq(res.length, 1);
-assert.docEq(res[0], {a: 1});
-
-// Tests that a non-sparse index {missing: 1} can be used to answer the $expr query.
-assert.commandWorked(coll.createIndex({"missing": 1}));
-
-// Explain the query, and determine whether an indexed solution is available.
-let ixScans = getPlanStages(getWinningPlan(coll.find(exprQuery).explain().queryPlanner), "IXSCAN");
-
-// Verify that the winning plan uses the $** index with the expected bounds.
-assert.gt(ixScans.length, 0, ixScans);
-assert.eq("missing_1", ixScans[0].indexName, ixScans);
-
-// Run the same query. A complete result will be returned.
-res = coll.find(exprQuery, {_id: 0}).toArray();
-assert.eq(res.length, 1);
-assert.docEq(res[0], {a: 1});
-
-// Drop the non-sparse index and create a sparse index with the same key pattern.
-assert.commandWorked(coll.dropIndex("missing_1"));
-assert.commandWorked(coll.createIndex({'missing': 1}, {'sparse': true}));
-
-// Run the same query to test that a COLLSCAN plan is used rather than an indexed plan.
-const collScans =
- getPlanStages(getWinningPlan(coll.find(exprQuery).explain().queryPlanner), "COLLSCAN");
-
-// Verify that the winning plan uses the $** index with the expected bounds.
-assert.gt(collScans.length, 0, collScans);
-
-// Test that a sparse index can be hinted to answer $expr query but incomplete results in returned,
-// because the document is not indexed by the sparse index.
-res = coll.find(exprQuery, {_id: 0}).hint("missing_1").toArray();
-assert.eq(res.length, 0);
-
-ixScans = getPlanStages(
- getWinningPlan(coll.find(exprQuery).hint("missing_1").explain().queryPlanner), "IXSCAN");
-
-assert.gt(ixScans.length, 0, ixScans);
-assert.eq("missing_1", ixScans[0].indexName, ixScans);
-assert.eq(true, ixScans[0].isSparse, ixScans);
-}());
diff --git a/jstests/core/index_elemmatch1.js b/jstests/core/index_elemmatch1.js
new file mode 100644
index 00000000000..6277ca9c42d
--- /dev/null
+++ b/jstests/core/index_elemmatch1.js
@@ -0,0 +1,39 @@
+/**
+ * Tests find with $elemMatch when supporting indexes are in place.
+ * @tags: [
+ * assumes_balancer_off,
+ * assumes_read_concern_local,
+ * ]
+ */
+(function() {
+"use strict";
+
+const coll = db.index_elemmatch1;
+coll.drop();
+
+let x = 0;
+let y = 0;
+const bulk = coll.initializeUnorderedBulkOp();
+for (let a = 0; a < 10; a++) {
+ for (let b = 0; b < 10; b++) {
+ bulk.insert({a: a, b: b % 10, arr: [{x: x++ % 10, y: y++ % 10}]});
+ }
+}
+assert.commandWorked(bulk.execute());
+
+assert.commandWorked(coll.createIndex({a: 1, b: 1}));
+assert.commandWorked(coll.createIndex({"arr.x": 1, a: 1}));
+
+const query = {
+ a: 5,
+ b: {$in: [1, 3, 5]},
+ arr: {$elemMatch: {x: 5, y: 5}}
+};
+
+const count = coll.find(query).itcount();
+assert.eq(count, 1);
+
+const explain = coll.find(query).hint({"arr.x": 1, a: 1}).explain("executionStats");
+assert.commandWorked(explain);
+assert.eq(count, explain.executionStats.totalKeysExamined, explain);
+})();
diff --git a/jstests/core/elemmatch_index.js b/jstests/core/index_elemmatch2.js
index f0aaf35cdba..33988cb945e 100644
--- a/jstests/core/elemmatch_index.js
+++ b/jstests/core/index_elemmatch2.js
@@ -2,7 +2,6 @@
* Test that queries containing $elemMatch correctly use an index if each child expression is
* compatible with the index.
* @tags: [
- * assumes_balancer_off,
* assumes_read_concern_local,
* ]
*/
@@ -65,57 +64,4 @@ assertIndexResults(coll, {a: {$elemMatch: {$not: {$in: [/^a/]}}}}, false, 3);
coll.dropIndexes();
assert.commandWorked(coll.createIndex({a: 1}));
assertIndexResults(coll, {a: {$elemMatch: {$not: {$in: [/^a/]}}}}, false, 3);
-
-(function() {
-assert(coll.drop());
-assert.commandWorked(coll.insert({a: [{b: {c: "x"}}]}));
-assert.commandWorked(coll.createIndex({"a.b.c": 1}));
-
-// Tests $elemMatch with path components that are empty strings. The system should not attempt to
-// use the index for these queries.
-assertIndexResults(coll, {"": {$elemMatch: {"a.b.c": "x"}}}, false, 0);
-assertIndexResults(coll, {"": {$all: [{$elemMatch: {"a.b.c": "x"}}]}}, false, 0);
-assertIndexResults(coll, {a: {$elemMatch: {"": {$elemMatch: {"b.c": "x"}}}}}, false, 0);
-
-// Tests $elemMatch with supporting index and no path components that are empty strings.
-assertIndexResults(coll, {a: {$elemMatch: {"b.c": "x"}}}, true, 1);
-assertIndexResults(coll, {a: {$all: [{$elemMatch: {"b.c": "x"}}]}}, true, 1);
-
-// Tests that $elemMatch with path components that are empty strings are correctly handled in the
-// plan enumerator in case if an index is used on another predicate of the query.
-assertIndexResults(coll, {$and: [{"a.b.c": "x"}, {"": {$elemMatch: {"a.b.c": "x"}}}]}, true, 0);
-
-assertIndexResults(coll, {$and: [{"a.b.c": "x"}, {"a.b.c": {$elemMatch: {"": "x"}}}]}, true, 0);
-})();
-
-(function() {
-const coll = db.index_elemmatch1;
-coll.drop();
-
-let x = 0;
-let y = 0;
-const bulk = coll.initializeUnorderedBulkOp();
-for (let a = 0; a < 10; a++) {
- for (let b = 0; b < 10; b++) {
- bulk.insert({a: a, b: b % 10, arr: [{x: x++ % 10, y: y++ % 10}]});
- }
-}
-assert.commandWorked(bulk.execute());
-
-assert.commandWorked(coll.createIndex({a: 1, b: 1}));
-assert.commandWorked(coll.createIndex({"arr.x": 1, a: 1}));
-
-const query = {
- a: 5,
- b: {$in: [1, 3, 5]},
- arr: {$elemMatch: {x: 5, y: 5}}
-};
-
-const count = coll.find(query).itcount();
-assert.eq(count, 1);
-
-const explain = coll.find(query).hint({"arr.x": 1, a: 1}).explain("executionStats");
-assert.commandWorked(explain);
-assert.eq(count, explain.executionStats.totalKeysExamined, explain);
-})();
})();
diff --git a/jstests/core/index_filter_commands.js b/jstests/core/index_filter_commands.js
index 6e5f5c5726a..6c5ff8920c8 100644
--- a/jstests/core/index_filter_commands.js
+++ b/jstests/core/index_filter_commands.js
@@ -30,8 +30,7 @@
* assumes_read_preference_unchanged,
* assumes_unsharded_collection,
* does_not_support_stepdowns,
- * requires_fcv_60,
- * references_foreign_collection,
+ * requires_fcv_60
* ]
*/
diff --git a/jstests/core/index_partial_create_drop.js b/jstests/core/index_partial_create_drop.js
index c0a095b30df..800ad6ab64e 100644
--- a/jstests/core/index_partial_create_drop.js
+++ b/jstests/core/index_partial_create_drop.js
@@ -13,7 +13,7 @@
// Test partial index creation and drops.
-load("jstests/libs/feature_flag_util.js");
+load("jstests/core/timeseries/libs/timeseries.js");
(function() {
"use strict";
@@ -46,7 +46,7 @@ assert.commandFailed(
assert.commandFailed(coll.createIndex(
{x: 1}, {partialFilterExpression: {$expr: {$eq: [{$trim: {input: "$x"}}, "hi"]}}}));
-if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
// Only top-level $and is permitted in a partial filter expression.
assert.commandFailedWithCode(coll.createIndex({x: 1}, {
partialFilterExpression:
diff --git a/jstests/core/index_partial_read_ops.js b/jstests/core/index_partial_read_ops.js
index 2071b2d129c..4f1229888f7 100644
--- a/jstests/core/index_partial_read_ops.js
+++ b/jstests/core/index_partial_read_ops.js
@@ -10,7 +10,8 @@
// Include helpers for analyzing explain output.
load("jstests/libs/analyze_plan.js");
-load("jstests/libs/feature_flag_util.js");
+
+load("jstests/core/timeseries/libs/timeseries.js");
(function() {
"use strict";
@@ -132,7 +133,7 @@ const coll = db.index_partial_read_ops;
assert(isCollscan(db, coll.explain().find({a: {$lt: 0}}).finish()));
})();
-if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
jsTest.log(
"Skipping partialFilterExpression testing for $in, $or and non-top level $and as timeseriesMetricIndexesEnabled is false");
return;
diff --git a/jstests/core/index_prepareUnique.js b/jstests/core/index_prepareUnique.js
index 196e80a1864..97b3d0ef874 100644
--- a/jstests/core/index_prepareUnique.js
+++ b/jstests/core/index_prepareUnique.js
@@ -1,17 +1,21 @@
/**
- * Tests that the createIndex command accepts a prepareUnique field and works accordingly.
+ * Tests that the createIndex command accepts a prepareUnique field and works accordingly
+ * then.
*
- * @tags: [assumes_no_implicit_collection_creation_after_drop]
+ * @tags: [requires_fcv_53]
*/
(function() {
"use strict";
-load("jstests/libs/feature_flag_util.js");
-
const coll = db.index_prepareUnique;
coll.drop();
-if (!FeatureFlagUtil.isEnabled(db, "CollModIndexUnique")) {
+const collModIndexUniqueEnabled = assert
+ .commandWorked(db.getMongo().adminCommand(
+ {getParameter: 1, featureFlagCollModIndexUnique: 1}))
+ .featureFlagCollModIndexUnique.value;
+
+if (!collModIndexUniqueEnabled) {
jsTestLog('Skipping test because the collMod unique index feature flag is disabled.');
return;
}
@@ -44,4 +48,4 @@ indexesWithComments = coll.getIndexes().filter(function(doc) {
return friendlyEqual(doc.prepareUnique, true);
});
assert.eq(0, indexesWithComments.length);
-})();
+})(); \ No newline at end of file
diff --git a/jstests/core/index_stats.js b/jstests/core/index_stats.js
index b0abd2e35a1..43df9a63ed1 100644
--- a/jstests/core/index_stats.js
+++ b/jstests/core/index_stats.js
@@ -12,25 +12,18 @@
// # Tenant migrations passthrough suites automatically retry operations on TenantMigrationAborted
// # errors.
// tenant_migration_incompatible,
-// references_foreign_collection,
// ]
(function() {
"use strict";
load("jstests/libs/analyze_plan.js");
-load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-load('jstests/libs/fixture_helpers.js'); // For 'FixtureHelpers'
+load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
var colName = "jstests_index_stats";
var col = db[colName];
col.drop();
-function checkSBEEnabledOnHostingDB(db, featureFlags = []) {
- return checkSBEEnabled(FixtureHelpers.getPrimaryForNodeHostingDatabase(db).getDB(db.getName()),
- featureFlags);
-}
-
var getUsageCount = function(indexName, collection) {
collection = collection || col;
var cursor = collection.aggregate([{$indexStats: {}}]);
@@ -241,7 +234,7 @@ assert.eq(2,
])
.itcount());
assert.eq(1, getUsageCount("_id_", col), "Expected aggregation to use _id index");
-if (!checkSBEEnabledOnHostingDB(db, ["featureFlagSBELookupPushdown"])) {
+if (!checkSBEEnabled(db, ["featureFlagSBELookupPushdown"])) {
assert.eq(2,
getUsageCount("_id_", foreignCollection),
"Expected each lookup to be tracked as an index use");
@@ -279,7 +272,7 @@ const pipeline = [
];
assert.eq(2, col.aggregate(pipeline).itcount());
assert.eq(1, getUsageCount("_id_", col), "Expected aggregation to use _id index");
-if (!checkSBEEnabledOnHostingDB(db, ["featureFlagSBELookupPushdown"])) {
+if (!checkSBEEnabled(db, ["featureFlagSBELookupPushdown"])) {
assert.eq(2,
getUsageCount("_id_", foreignCollection),
"Expected each lookup to be tracked as an index use");
diff --git a/jstests/core/json_schema/json_schema.js b/jstests/core/json_schema/json_schema.js
index a69db77c60d..c1e06344498 100644
--- a/jstests/core/json_schema/json_schema.js
+++ b/jstests/core/json_schema/json_schema.js
@@ -1,7 +1,7 @@
// listCollections tests expect that a collection is not implicitly created after a drop.
// @tags: [
// assumes_no_implicit_collection_creation_after_drop,
-// requires_non_retryable_commands
+// requires_non_retryable_commands,
// ]
/**
diff --git a/jstests/core/json_schema/misc_validation.js b/jstests/core/json_schema/misc_validation.js
index 569d98be258..58e76fc0d68 100644
--- a/jstests/core/json_schema/misc_validation.js
+++ b/jstests/core/json_schema/misc_validation.js
@@ -19,7 +19,6 @@
* requires_replication,
* # This test depends on hardcoded database name equality.
* tenant_migration_incompatible,
- * references_foreign_collection,
* ]
*/
(function() {
diff --git a/jstests/core/latch_analyzer.js b/jstests/core/latch_analyzer.js
index 96c20d9c320..73aa652c6c1 100644
--- a/jstests/core/latch_analyzer.js
+++ b/jstests/core/latch_analyzer.js
@@ -1,7 +1,7 @@
/**
* Verify that the LatchAnalyzer is working to expectations
*
- * @tags: [multiversion_incompatible, no_selinux, requires_latch_analyzer]
+ * @tags: [multiversion_incompatible, no_selinux]
*/
(function() {
diff --git a/jstests/core/list_collections_name_only.js b/jstests/core/list_collections_name_only.js
index bd7bb7e249d..0db5ac8770f 100644
--- a/jstests/core/list_collections_name_only.js
+++ b/jstests/core/list_collections_name_only.js
@@ -2,7 +2,7 @@
* Test nameOnly option of listCollections
*
* @tags: [
- * # We expect the collection to exist when running listCollections
+ * // We expect the collection to exist when running listCollections
* does_not_support_stepdowns
* ]
*/
diff --git a/jstests/core/map_reduce_subplanning.js b/jstests/core/map_reduce_subplanning.js
deleted file mode 100644
index 35fed994ba8..00000000000
--- a/jstests/core/map_reduce_subplanning.js
+++ /dev/null
@@ -1,47 +0,0 @@
-// The test runs commands that are not allowed with security token: mapReduce.
-// @tags: [
-// not_allowed_with_security_token,
-// does_not_support_stepdowns,
-// requires_fastcount,
-// requires_getmore,
-// requires_non_retryable_writes,
-// # This test has statements that do not support non-local read concern.
-// does_not_support_causal_consistency,
-// # Uses mapReduce command.
-// requires_scripting,
-// ]
-
-load("jstests/aggregation/extras/utils.js"); // For resultsEq
-(function() {
-"use strict";
-
-const coll = db.map_reduce_subplanning;
-coll.drop();
-db.getCollection("mrOutput").drop();
-
-coll.createIndex({a: 1, c: 1});
-coll.createIndex({b: 1, c: 1});
-coll.createIndex({a: 1});
-coll.createIndex({b: 1});
-
-assert.commandWorked(coll.insert({a: 2}));
-assert.commandWorked(coll.insert({b: 3}));
-assert.commandWorked(coll.insert({b: 3}));
-assert.commandWorked(coll.insert({a: 2, b: 3}));
-
-assert.commandWorked(coll.mapReduce(
- function() {
- if (!this.hasOwnProperty('a')) {
- emit('a', 0);
- } else {
- emit('a', this.a);
- }
- },
- function(key, vals) {
- return vals.reduce((a, b) => a + b, 0);
- },
- {out: {merge: "mrOutput"}, query: {$or: [{a: 2}, {b: 3}]}}));
-
-assert(resultsEq([{"_id": "a", "value": 4}], db.getCollection("mrOutput").find().toArray()),
- db.getCollection("mrOutput").find().toArray());
-})();
diff --git a/jstests/core/match_with_and_or_lockstep_enumeration.js b/jstests/core/match_with_and_or_lockstep_enumeration.js
deleted file mode 100644
index 3c16f63d6ab..00000000000
--- a/jstests/core/match_with_and_or_lockstep_enumeration.js
+++ /dev/null
@@ -1,110 +0,0 @@
-
-/**
- * Test a particular nested $and/$or query. This test was designed to reproduce SERVER-83091, a bug
- * in which this query could trigger an infinite loop during plan enumeration.
- *
- * @tags: [
- * # We need to set a parameter which is meaningful only on mongod.
- * assumes_against_mongod_not_mongos,
- * # We expect to be reading from the same node where we configured a parameter.
- * assumes_read_preference_unchanged,
- * # Runs the setParameter command, which cannot work in passthroughs that have stepdowns.
- * does_not_support_stepdowns,
- * ]
- */
-(function() {
-"use strict";
-
-const coll = db.and_or_lockstep_coll;
-coll.drop();
-
-// We test running the $and/$or query with both lockstep $or enumeration enabled and with it
-// disabled. SERVER-83091 only affected lockstep $or enumeration, which is disabled by default in
-// this branch.
-const paramName = "internalQueryEnumerationPreferLockstepOrEnumeration";
-
-// At the time when SERVER-83091 was filed, match expression rewrites would rewrite the {b: 4} and
-// {b: 5} to {b: {$in: [4, 5]}}, resulting in a nested $or predicate which looks like this:
-//
-// $and
-// a $eq 1
-// $or
-// b $in [ 4, 5 ]
-// $or
-// $and
-// b $eq 2
-// c $eq 3
-// b $in [ 6, 7 ]
-//
-// The fact that this rewrite could result in an $or with a direct $or child was key to reproducing
-// SERVER-83091. Note that SERVER-83602 improves the system such that it will not unnecessarily
-// generate an $or with a direct $or child.
-//
-// This nested $or is never simplified later on. (In constrast, if the query is originally expressed
-// with a nested $or it will get simplified; that's why the repro requires an $or containing some
-// predicates that get rewritten to an $in.) The bug related to how lockstep enumeration dealt with
-// nested $or nodes. A very particular query structure was also necessary, because to exercise the
-// bug we needed to get into a state where the inner $or reached its limit on the number of plans it
-// was willing to enumerate before the outer $or did.
-const predicate = {
- a: 1,
- $or: [
- {b: 2, c: 3},
- {b: 4},
- {b: 5},
- {
- b: {$in: [6, 7]},
- }
- ],
-};
-
-const docs = [
- // No "a" field.
- {x: 2},
-
- // "a" does not match.
- {a: 2, x: 2},
-
- // No matching "b" or "c" value.
- {a: 1, x: 2, b: 8},
- {a: 1, x: 2, b: 2, c: 9},
-
- // Matching values.
- {a: 1, x: 2, b: 2, c: 3},
- {a: 1, x: 2, b: 4},
- {a: 1, x: 2, b: 5},
- {a: 1, x: 2, b: 6},
- {a: 1, x: 2, b: 7},
-];
-const kNumMatchingValues = 5;
-assert.commandWorked(coll.insert(docs));
-
-const indexes = [
- {a: 1, b: 1},
- {a: 1, c: 1},
-];
-for (let index of indexes) {
- assert.commandWorked(coll.createIndex(index));
-}
-
-function setLockstepOrParam(val) {
- assert.commandWorked(db.adminCommand({setParameter: 1, [paramName]: val}));
-}
-
-function runTest(lockstepOrEnabled) {
- setLockstepOrParam(lockstepOrEnabled);
- jsTestLog(`Lockstep $or enumeration enabled: ${lockstepOrEnabled}`);
- assert.eq(coll.find(predicate).itcount(), kNumMatchingValues);
-}
-
-// Get the default parameter value so it can be correctly reset if the test fails. Then run the test
-// with lockstep $or plan enumeration enabled and with it disabled.
-const origParamValue =
- assert.commandWorked(db.adminCommand({getParameter: 1, [paramName]: 1}))[paramName];
-try {
- runTest(true);
- runTest(false);
-} finally {
- setLockstepOrParam(origParamValue);
-}
-}());
diff --git a/jstests/core/monotonic_date_operations.js b/jstests/core/monotonic_date_operations.js
deleted file mode 100644
index 5e28967bc44..00000000000
--- a/jstests/core/monotonic_date_operations.js
+++ /dev/null
@@ -1,408 +0,0 @@
-/**
- * Tests that date expressions remain monotonic despite timezone changes.
- */
-
-(function() {
-"use strict";
-
-const coll = db.monotonic_date_operations;
-
-const runTest = function(documents, pipeline, expectedDocs) {
- coll.drop();
- assert.commandWorked(coll.insertMany(documents));
- pipeline.push({$sort: {_id: 1}});
- assert.eq(coll.aggregate(pipeline).toArray(), expectedDocs);
-};
-
-const dateFormat = "%Y-%m-%dT%H:%M:%S.%L%z";
-
-// New York DST fall switch
-runTest(
- [
- {_id: 0, time: ISODate("2022-11-06T03:00:00Z")}, // 2022-11-05T23:00:00 in New York
- {_id: 1, time: ISODate("2022-11-06T05:00:00Z")},
- {_id: 2, time: ISODate("2022-11-06T05:30:00Z")},
- {_id: 3, time: ISODate("2022-11-06T06:00:00Z")}, // Moment of DST switch
- {_id: 4, time: ISODate("2022-11-06T06:30:00Z")},
- {_id: 5, time: ISODate("2022-11-06T07:00:00Z")},
- ],
- [{
- $project: {
- localTime: {
- $dateToString: {
- date: "$time",
- format: dateFormat,
- timezone: "America/New_York",
- }
- },
- diffMinutes: {
- $dateDiff: {
- startDate: ISODate("2022-11-06T04:00:00Z"),
- endDate: "$time",
- unit: "minute",
- timezone: "America/New_York",
- }
- },
- diffDays: {
- $dateDiff: {
- startDate: ISODate("2022-11-06T04:00:00Z"),
- endDate: "$time",
- unit: "day",
- timezone: "America/New_York",
- }
- }
- }
- }],
- [
- {
- _id: 0,
- localTime: "2022-11-05T23:00:00.000-0400",
- diffMinutes: NumberLong(-60),
- diffDays: NumberLong(-1)
- },
- {
- _id: 1,
- localTime: "2022-11-06T01:00:00.000-0400",
- diffMinutes: NumberLong(60),
- diffDays: NumberLong(0)
- },
- {
- _id: 2,
- localTime: "2022-11-06T01:30:00.000-0400",
- diffMinutes: NumberLong(90),
- diffDays: NumberLong(0)
- },
- {
- _id: 3,
- localTime: "2022-11-06T01:00:00.000-0500",
- diffMinutes: NumberLong(120),
- diffDays: NumberLong(0)
- },
- {
- _id: 4,
- localTime: "2022-11-06T01:30:00.000-0500",
- diffMinutes: NumberLong(150),
- diffDays: NumberLong(0)
- },
- {
- _id: 5,
- localTime: "2022-11-06T02:00:00.000-0500",
- diffMinutes: NumberLong(180),
- diffDays: NumberLong(0)
- }
- ]);
-
-// New York DST spring switch
-runTest(
- [
- {_id: 0, time: ISODate("2022-03-13T06:00:00Z")}, // 2022-03-13T01:00:00 in New York
- {_id: 1, time: ISODate("2022-03-13T06:30:00Z")},
- {_id: 2, time: ISODate("2022-03-13T07:00:00Z")}, // Moment of DST switch
- {_id: 3, time: ISODate("2022-03-13T07:30:00Z")},
- {_id: 4, time: ISODate("2022-03-13T08:00:00Z")},
- ],
- [{
- $project: {
- localTime: {
- $dateToString: {
- date: "$time",
- format: dateFormat,
- timezone: "America/New_York",
- }
- },
- diffMinutes: {
- $dateDiff: {
- startDate: ISODate("2022-03-13T00:00:00Z"),
- endDate: "$time",
- unit: "minute",
- timezone: "America/New_York",
- }
- },
- diffDays: {
- $dateDiff: {
- startDate: ISODate("2022-03-13T00:00:00Z"),
- endDate: "$time",
- unit: "day",
- timezone: "America/New_York",
- }
- }
- }
- }],
- [
- {
- _id: 0,
- localTime: "2022-03-13T01:00:00.000-0500",
- diffMinutes: NumberLong(360),
- diffDays: NumberLong(1)
- },
- {
- _id: 1,
- localTime: "2022-03-13T01:30:00.000-0500",
- diffMinutes: NumberLong(390),
- diffDays: NumberLong(1)
- },
- {
- _id: 2,
- localTime: "2022-03-13T03:00:00.000-0400",
- diffMinutes: NumberLong(420),
- diffDays: NumberLong(1)
- },
- {
- _id: 3,
- localTime: "2022-03-13T03:30:00.000-0400",
- diffMinutes: NumberLong(450),
- diffDays: NumberLong(1)
- },
- {
- _id: 4,
- localTime: "2022-03-13T04:00:00.000-0400",
- diffMinutes: NumberLong(480),
- diffDays: NumberLong(1)
- },
- ]);
-
-// Samoa day skip
-runTest(
- [
- {_id: 0, time: ISODate("2011-12-29T10:00:00Z")},
- {_id: 1, time: ISODate("2011-12-30T09:00:00Z")}, // 2011-12-29T23:00:00 in Apia, Samoa
- {_id: 2, time: ISODate("2011-12-30T09:30:00Z")},
- {_id: 3, time: ISODate("2011-12-30T10:00:00Z")}, // Day skip moment
- {_id: 4, time: ISODate("2011-12-30T10:30:00Z")},
- {_id: 5, time: ISODate("2011-12-30T11:00:00Z")},
- {_id: 6, time: ISODate("2011-12-30T10:00:00Z")},
- ],
- [{
- $project: {
- localTime: {
- $dateToString: {
- date: "$time",
- format: dateFormat,
- timezone: "Pacific/Apia",
- }
- },
- diffMinutes: {
- $dateDiff: {
- startDate: ISODate("2011-12-28T10:00:00Z"),
- endDate: "$time",
- unit: "minute",
- timezone: "Pacific/Apia",
- }
- },
- diffDays: {
- $dateDiff: {
- startDate: ISODate("2011-12-28T10:00:00Z"),
- endDate: "$time",
- unit: "day",
- timezone: "Pacific/Apia",
- }
- }
- }
- }],
- [
- {
- _id: 0,
- localTime: "2011-12-29T00:00:00.000-1000",
- diffMinutes: NumberLong(1440),
- diffDays: NumberLong(1)
- },
- {
- _id: 1,
- localTime: "2011-12-29T23:00:00.000-1000",
- diffMinutes: NumberLong(2820),
- diffDays: NumberLong(1)
- },
- {
- _id: 2,
- localTime: "2011-12-29T23:30:00.000-1000",
- diffMinutes: NumberLong(2850),
- diffDays: NumberLong(1)
- },
- {
- _id: 3,
- localTime: "2011-12-31T00:00:00.000+1400",
- diffMinutes: NumberLong(2880),
- diffDays: NumberLong(3)
- },
- {
- _id: 4,
- localTime: "2011-12-31T00:30:00.000+1400",
- diffMinutes: NumberLong(2910),
- diffDays: NumberLong(3)
- },
- {
- _id: 5,
- localTime: "2011-12-31T01:00:00.000+1400",
- diffMinutes: NumberLong(2940),
- diffDays: NumberLong(3)
- },
- {
- _id: 6,
- localTime: "2011-12-31T00:00:00.000+1400",
- diffMinutes: NumberLong(2880),
- diffDays: NumberLong(3)
- },
- ]);
-
-// Sao Paulo, Brazil DST fall switch
-runTest(
- [
- {
- _id: 0,
- time: ISODate("2018-11-04T02:00:00Z")
- }, // 2018-11-03T23:00:00 in Sao Paulo, Brazil
- {_id: 1, time: ISODate("2018-11-04T02:30:00Z")},
- {_id: 2, time: ISODate("2018-11-04T03:00:00Z")}, // Moment of DST switch
- {_id: 3, time: ISODate("2018-11-04T03:30:00Z")},
- {_id: 4, time: ISODate("2018-11-04T04:00:00Z")},
- {_id: 5, time: ISODate("2018-11-04T04:30:00Z")},
- ],
- [{
- $project: {
- localTime: {
- $dateToString: {
- date: "$time",
- format: dateFormat,
- timezone: "America/Sao_Paulo",
- }
- },
- diffMinutes: {
- $dateDiff: {
- startDate: ISODate("2018-11-04T02:00:00Z"),
- endDate: "$time",
- unit: "minute",
- timezone: "America/Sao_Paulo",
- }
- },
- diffDays: {
- $dateDiff: {
- startDate: ISODate("2018-11-04T02:00:00Z"),
- endDate: "$time",
- unit: "day",
- timezone: "America/Sao_Paulo",
- }
- }
- }
- }],
- [
- {
- _id: 0,
- localTime: "2018-11-03T23:00:00.000-0300",
- diffMinutes: NumberLong(0),
- diffDays: NumberLong(0)
- },
- {
- _id: 1,
- localTime: "2018-11-03T23:30:00.000-0300",
- diffMinutes: NumberLong(30),
- diffDays: NumberLong(0)
- },
- {
- _id: 2,
- localTime: "2018-11-04T01:00:00.000-0200",
- diffMinutes: NumberLong(60),
- diffDays: NumberLong(1)
- },
- {
- _id: 3,
- localTime: "2018-11-04T01:30:00.000-0200",
- diffMinutes: NumberLong(90),
- diffDays: NumberLong(1)
- },
- {
- _id: 4,
- localTime: "2018-11-04T02:00:00.000-0200",
- diffMinutes: NumberLong(120),
- diffDays: NumberLong(1)
- },
- {
- _id: 5,
- localTime: "2018-11-04T02:30:00.000-0200",
- diffMinutes: NumberLong(150),
- diffDays: NumberLong(1)
- },
- ]);
-
-// Sao Paulo, Brazil DST sprint switch
-runTest(
- [
- {_id: 0, time: ISODate("2018-02-18T00:30:00Z")}, // 2018-02-17T22:30:00 in Sao Paulo, Brazi
- {_id: 1, time: ISODate("2018-02-18T01:00:00Z")},
- {_id: 2, time: ISODate("2018-02-18T01:30:00Z")},
- {_id: 3, time: ISODate("2018-02-18T02:00:00Z")}, // Moment of DST switch
- {_id: 4, time: ISODate("2018-02-18T02:30:00Z")},
- {_id: 5, time: ISODate("2018-02-18T03:00:00Z")},
- {_id: 6, time: ISODate("2018-02-18T03:30:00Z")},
- ],
- [{
- $project: {
- localTime: {
- $dateToString: {
- date: "$time",
- format: dateFormat,
- timezone: "America/Sao_Paulo",
- }
- },
- diffMinutes: {
- $dateDiff: {
- startDate: ISODate("2018-02-18T00:30:00Z"),
- endDate: "$time",
- unit: "minute",
- timezone: "America/Sao_Paulo",
- }
- },
- diffDays: {
- $dateDiff: {
- startDate: ISODate("2018-02-18T00:30:00Z"),
- endDate: "$time",
- unit: "day",
- timezone: "America/Sao_Paulo",
- }
- }
- }
- }],
- [
- {
- _id: 0,
- localTime: "2018-02-17T22:30:00.000-0200",
- diffMinutes: NumberLong(0),
- diffDays: NumberLong(0)
- },
- {
- _id: 1,
- localTime: "2018-02-17T23:00:00.000-0200",
- diffMinutes: NumberLong(30),
- diffDays: NumberLong(0)
- },
- {
- _id: 2,
- localTime: "2018-02-17T23:30:00.000-0200",
- diffMinutes: NumberLong(60),
- diffDays: NumberLong(0)
- },
- {
- _id: 3,
- localTime: "2018-02-17T23:00:00.000-0300",
- diffMinutes: NumberLong(90),
- diffDays: NumberLong(0)
- },
- {
- _id: 4,
- localTime: "2018-02-17T23:30:00.000-0300",
- diffMinutes: NumberLong(120),
- diffDays: NumberLong(0)
- },
- {
- _id: 5,
- localTime: "2018-02-18T00:00:00.000-0300",
- diffMinutes: NumberLong(150),
- diffDays: NumberLong(1)
- },
- {
- _id: 6,
- localTime: "2018-02-18T00:30:00.000-0300",
- diffMinutes: NumberLong(180),
- diffDays: NumberLong(1)
- }
- ]);
-})();
diff --git a/jstests/core/mr_single_reduce.js b/jstests/core/mr_single_reduce.js
deleted file mode 100644
index 380182d61fb..00000000000
--- a/jstests/core/mr_single_reduce.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// @tags: [
-// # Step-down can cause mapReduce to fail.
-// does_not_support_stepdowns,
-// ]
-(function() {
-"use strict";
-const coll = db.bar;
-
-assert.commandWorked(coll.insert({x: 1}));
-
-const map = function() {
- emit(0, "mapped value");
-};
-
-const reduce = function(key, values) {
- return "reduced value";
-};
-
-const res = assert.commandWorked(
- db.runCommand({mapReduce: 'bar', map: map, reduce: reduce, out: {inline: 1}}));
-assert.eq(res.results[0], {_id: 0, value: "reduced value"});
-}());
diff --git a/jstests/core/nested_or_duplicate_predicates_index_scan.js b/jstests/core/nested_or_duplicate_predicates_index_scan.js
deleted file mode 100644
index fae1c8fff9b..00000000000
--- a/jstests/core/nested_or_duplicate_predicates_index_scan.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Test a nested $or query which reproduces SERVER-84013, a bug in the subplanner. This bug had to
- * do with the subplanner assuming that multiple invocations of MatchExpression::optimize() yielded
- * the same expressions, which turns out not to be the case. The queries in this regression test
- * excerise the $or -> $in rewrite which produce new $in expressions which themselves could be
- * further optimized.
- */
-(function() {
-"use strict";
-
-const coll = db.server84013;
-coll.drop();
-
-const docs = [
- {_id: 0, Country: {_id: "US"}, State: "California", City: "SanFrancisco"},
- {_id: 1, Country: {_id: "US"}, State: "NewYork", City: "Buffalo"},
-];
-
-assert.commandWorked(coll.insert(docs));
-assert.commandWorked(coll.createIndex({"Country._id": 1, "State": 1}));
-
-assert.eq(docs.slice(0, 1),
- coll.find({
- "$or": [
- {"Country._id": "DNE"},
- {
- "Country._id": "US",
- "State": "California",
- "$or": [{"City": "SanFrancisco"}, {"City": {"$in": ["SanFrancisco"]}}]
- }
- ]
- })
- .toArray());
-
-assert.eq(docs.slice(0, 1),
- coll.find({
- "$or": [
- {"Country._id": "DNE"},
- {
- "Country._id": "US",
- "State": "California",
- "$or": [
- {"City": "SanFrancisco"},
- {"City": {$in: ["SanFrancisco"]}},
- {"Country._id": "DNE"},
- ]
- },
- ]
- })
- .toArray());
-})();
diff --git a/jstests/core/no_db_created.js b/jstests/core/no_db_created.js
index d2d5bbcae7d..bb0d998a3fe 100644
--- a/jstests/core/no_db_created.js
+++ b/jstests/core/no_db_created.js
@@ -1,4 +1,4 @@
-// @tags: [requires_non_retryable_commands, uses_compact]
+// @tags: [requires_non_retryable_commands]
// checks that operations do not create a database
@@ -34,4 +34,4 @@ assert.commandFailed(coll.runCommand("collMod", {expireAfterSeconds: 1}));
noDB(mydb);
assert.commandWorked(coll.insert({}));
mydb.dropDatabase();
-}());
+}()); \ No newline at end of file
diff --git a/jstests/core/notablescan.js b/jstests/core/notablescan.js
new file mode 100644
index 00000000000..baef5d56ae6
--- /dev/null
+++ b/jstests/core/notablescan.js
@@ -0,0 +1,61 @@
+// check notablescan mode
+//
+// @tags: [
+// assumes_against_mongod_not_mongos,
+// # This test attempts to perform read operations after having enabled the notablescan server
+// # parameter. The former operations may be routed to a secondary in the replica set, whereas the
+// # latter must be routed to the primary.
+// assumes_read_preference_unchanged,
+// assumes_superuser_permissions,
+// does_not_support_stepdowns,
+// # Server parameters are stored in-memory only so are not transferred onto the recipient. This
+// # test sets the server parameter "notablescan" to force the node to not execute queries that
+// # require a collection scan and return an error.
+// tenant_migration_incompatible,
+// ]
+
+t = db.test_notablescan;
+t.drop();
+
+try {
+ assert.commandWorked(db._adminCommand({setParameter: 1, notablescan: true}));
+ // commented lines are SERVER-2222
+ if (0) { // SERVER-2222
+ assert.throws(function() {
+ t.find({a: 1}).toArray();
+ });
+ }
+ t.save({a: 1});
+ assert.throws(function() {
+ t.count({a: 1});
+ });
+ if (0) {
+ assert.throws(function() {
+ t.find({}).toArray();
+ });
+ }
+ assert.eq(1, t.find({}).itcount()); // SERVER-274
+
+ let err = assert.throws(function() {
+ t.find({a: 1}).toArray();
+ });
+ assert.includes(err.toString(), "No indexed plans available, and running with 'notablescan'");
+
+ err = assert.throws(function() {
+ t.find({a: 1}).hint({$natural: 1}).toArray();
+ });
+ assert.includes(err.toString(),
+ "hint $natural is not allowed, because 'notablescan' is enabled");
+
+ t.createIndex({a: 1});
+ assert.eq(0, t.find({a: 1, b: 1}).itcount());
+ assert.eq(1, t.find({a: 1, b: null}).itcount());
+
+ // SERVER-4327
+ assert.eq(0, t.find({a: {$in: []}}).itcount());
+ assert.eq(0, t.find({a: {$in: []}, b: 0}).itcount());
+} finally {
+ // We assume notablescan was false before this test started and restore that
+ // expected value.
+ assert.commandWorked(db._adminCommand({setParameter: 1, notablescan: false}));
+}
diff --git a/jstests/core/null_query_semantics.js b/jstests/core/null_query_semantics.js
index aa9042c5ac5..1ff14cc710c 100644
--- a/jstests/core/null_query_semantics.js
+++ b/jstests/core/null_query_semantics.js
@@ -41,9 +41,6 @@ function testNullSemantics(coll) {
[{_id: "a_null", a: null}, {_id: "a_undefined", a: undefined}, {_id: "no_a"}];
assert(resultsEq(expected, noProjectResults), tojson(noProjectResults));
- const count = coll.count({a: {$eq: null}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find({a: {$eq: null}}, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), tojson(projectResults));
}());
@@ -60,9 +57,6 @@ function testNullSemantics(coll) {
];
assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
- const count = coll.count({a: {$ne: null}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find({a: {$ne: null}}, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), tojson(projectResults));
}());
@@ -78,9 +72,6 @@ function testNullSemantics(coll) {
{_id: "no_a"},
];
- const count = coll.count(query);
- assert.eq(count, expected.length);
-
assert(resultsEq(noProjectResults, expected), noProjectResults);
const projectResults = coll.find(query, projectToOnlyA).toArray();
@@ -98,9 +89,6 @@ function testNullSemantics(coll) {
{_id: "no_a"},
];
- const count = coll.count(query);
- assert.eq(count, expected.length);
-
assert(resultsEq(noProjectResults, expected), noProjectResults);
const projectResults = coll.find(query, projectToOnlyA).toArray();
@@ -118,9 +106,6 @@ function testNullSemantics(coll) {
{_id: "a_subobject_b_undefined", a: {b: undefined}},
];
- const count = coll.count(query);
- assert.eq(count, expected.length);
-
assert(resultsEq(noProjectResults, expected), noProjectResults);
const projectResults = coll.find(query, projectToOnlyA).toArray();
@@ -141,9 +126,6 @@ function testNullSemantics(coll) {
];
assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
- const count = coll.count(query);
- assert.eq(count, expected.length);
-
const projectResults = coll.find(query, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), projectResults);
}());
@@ -155,9 +137,6 @@ function testNullSemantics(coll) {
];
assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
- const count = coll.count({a: {$exists: false}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find({a: {$exists: false}}, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), tojson(projectResults));
}());
@@ -165,19 +144,17 @@ function testNullSemantics(coll) {
// Test the semantics of the query {"a.b": {$eq: null}}.
(function testDottedEqualsNull() {
const noProjectResults = coll.find({"a.b": {$eq: null}}).toArray();
- const expected = [
- {_id: "a_empty_subobject", a: {}},
- {_id: "a_null", a: null},
- {_id: "a_number", a: 4},
- {_id: "a_subobject_b_null", a: {b: null}},
- {_id: "a_subobject_b_undefined", a: {b: undefined}},
- {_id: "a_undefined", a: undefined},
- {_id: "no_a"}
- ];
- assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
-
- const count = coll.count({"a.b": {$eq: null}});
- assert.eq(count, expected.length);
+ assert(resultsEq(noProjectResults,
+ [
+ {_id: "a_empty_subobject", a: {}},
+ {_id: "a_null", a: null},
+ {_id: "a_number", a: 4},
+ {_id: "a_subobject_b_null", a: {b: null}},
+ {_id: "a_subobject_b_undefined", a: {b: undefined}},
+ {_id: "a_undefined", a: undefined},
+ {_id: "no_a"}
+ ]),
+ tojson(noProjectResults));
const projectResults = coll.find({"a.b": {$eq: null}}, projectToOnlyADotB).toArray();
assert(resultsEq(projectResults,
@@ -188,11 +165,8 @@ function testNullSemantics(coll) {
// Test the semantics of the query {"a.b": {$ne: null}}.
(function testDottedNotEqualsNull() {
const noProjectResults = coll.find({"a.b": {$ne: null}}).toArray();
- const expected = [{_id: "a_subobject_b_not_null", a: {b: "hi"}}];
- assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
-
- const count = coll.count({"a.b": {$ne: null}});
- assert.eq(count, expected.length);
+ assert(resultsEq(noProjectResults, [{_id: "a_subobject_b_not_null", a: {b: "hi"}}]),
+ tojson(noProjectResults));
const projectResults = coll.find({"a.b": {$ne: null}}, projectToOnlyADotB).toArray();
assert(resultsEq(projectResults, [{a: {b: "hi"}}]), tojson(projectResults));
@@ -209,9 +183,6 @@ function testNullSemantics(coll) {
];
assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
- const count = coll.count({"a.b": {$exists: false}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find({"a.b": {$exists: false}}, projectToOnlyADotB).toArray();
assert(resultsEq(projectResults, [{}, {a: {}}, {}, {}, {}]), tojson(projectResults));
}());
@@ -231,9 +202,6 @@ function testNullSemantics(coll) {
`Expected no results for query ${tojson(elemMatchQuery)}, got ` +
tojson(noProjectResults));
- const count = coll.count(elemMatchQuery);
- assert.eq(count, 0);
-
let projectResults = coll.find(elemMatchQuery, projectToOnlyA).toArray();
assert(resultsEq(projectResults, []),
`Expected no results for query ${tojson(elemMatchQuery)}, got ` +
@@ -282,9 +250,6 @@ function testNullSemantics(coll) {
];
assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
- const count = coll.count({a: {$eq: null}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find({a: {$eq: null}}, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), tojson(projectResults));
}());
@@ -309,9 +274,6 @@ function testNullSemantics(coll) {
];
assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
- const count = coll.count({a: {$ne: null}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find({a: {$ne: null}}, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), tojson(projectResults));
}());
@@ -335,8 +297,6 @@ function testNullSemantics(coll) {
{_id: "a_value_array_no_nulls", a: [1, "string", 4]},
];
assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
- const count = coll.count({a: {$not: {$gte: null}}});
- assert.eq(count, expected.length);
}());
// Test the semantics of the query {a: {$in: [null, <number>]}}.
@@ -354,9 +314,6 @@ function testNullSemantics(coll) {
assert(resultsEq(noProjectResults, expected), noProjectResults);
- const count = coll.count({a: {$in: [null, 75]}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find(query, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), projectResults);
}());
@@ -376,9 +333,6 @@ function testNullSemantics(coll) {
assert(resultsEq(noProjectResults, expected), noProjectResults);
- const count = coll.count({$or: [{a: null}, {a: 75}]});
- assert.eq(count, expected.length);
-
const projectResults = coll.find(query, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), projectResults);
}());
@@ -406,9 +360,6 @@ function testNullSemantics(coll) {
assert(resultsEq(noProjectResults, expected), noProjectResults);
- const count = coll.count({a: {$nin: [null, 75]}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find(query, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), projectResults);
}());
@@ -444,9 +395,6 @@ function testNullSemantics(coll) {
assert(resultsEq(noProjectResults, expected), noProjectResults);
- const count = coll.count({a: {$nin: [null, []]}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find(query, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), projectResults);
}());
@@ -472,9 +420,6 @@ function testNullSemantics(coll) {
assert(resultsEq(noProjectResults, expected), noProjectResults);
- const count = coll.count(query);
- assert.eq(count, expected.length);
-
const projectResults = coll.find(query, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), projectResults);
}());
@@ -490,9 +435,6 @@ function testNullSemantics(coll) {
];
assert(resultsEq(noProjectResults, expectedEqualToNull), tojson(noProjectResults));
- const count = coll.count({a: {$elemMatch: {$eq: null}}});
- assert.eq(count, expectedEqualToNull.length);
-
let projectResults = coll.find({a: {$elemMatch: {$eq: null}}}, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expectedEqualToNull)),
tojson(projectResults));
@@ -525,23 +467,25 @@ function testNullSemantics(coll) {
// value for "b".
(function testDottedEqualsNull() {
const noProjectResults = coll.find({"a.b": {$eq: null}}).toArray();
- const expected = [
- {_id: "a_empty_subobject", a: {}},
- {_id: "a_null", a: null},
- {_id: "a_number", a: 4},
- {_id: "a_subobject_b_null", a: {b: null}},
- {_id: "a_subobject_b_undefined", a: {b: undefined}},
- {_id: "a_undefined", a: undefined},
- {_id: "no_a"},
- {_id: "a_object_array_all_b_nulls", a: [{b: null}, {b: undefined}, {b: null}, {}]},
- {_id: "a_object_array_some_b_nulls", a: [{b: null}, {b: 3}, {b: null}]},
- {_id: "a_object_array_some_b_undefined", a: [{b: undefined}, {b: 3}]},
- {_id: "a_object_array_some_b_missing", a: [{b: 3}, {}]},
- ];
- assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
-
- const count = coll.count({"a.b": {$eq: null}});
- assert.eq(count, expected.length);
+ assert(
+ resultsEq(noProjectResults,
+ [
+ {_id: "a_empty_subobject", a: {}},
+ {_id: "a_null", a: null},
+ {_id: "a_number", a: 4},
+ {_id: "a_subobject_b_null", a: {b: null}},
+ {_id: "a_subobject_b_undefined", a: {b: undefined}},
+ {_id: "a_undefined", a: undefined},
+ {_id: "no_a"},
+ {
+ _id: "a_object_array_all_b_nulls",
+ a: [{b: null}, {b: undefined}, {b: null}, {}]
+ },
+ {_id: "a_object_array_some_b_nulls", a: [{b: null}, {b: 3}, {b: null}]},
+ {_id: "a_object_array_some_b_undefined", a: [{b: undefined}, {b: 3}]},
+ {_id: "a_object_array_some_b_missing", a: [{b: 3}, {}]},
+ ]),
+ tojson(noProjectResults));
const projectResults = coll.find({"a.b": {$eq: null}}, projectToOnlyADotB).toArray();
assert(resultsEq(projectResults,
@@ -564,20 +508,18 @@ function testNullSemantics(coll) {
// Test the semantics of the query {"a.b": {$ne: null}}.
(function testDottedNotEqualsNull() {
const noProjectResults = coll.find({"a.b": {$ne: null}}).toArray();
- const expected = [
- {_id: "a_subobject_b_not_null", a: {b: "hi"}},
- {_id: "a_double_array", a: [[]]},
- {_id: "a_empty_array", a: []},
- {_id: "a_object_array_no_b_nulls", a: [{b: 1}, {b: 3}, {b: "string"}]},
- {_id: "a_value_array_all_nulls", a: [null, null]},
- {_id: "a_value_array_no_nulls", a: [1, "string", 4]},
- {_id: "a_value_array_with_null", a: [1, "string", null, 4]},
- {_id: "a_value_array_with_undefined", a: [1, "string", undefined, 4]}
- ];
- assert(resultsEq(noProjectResults, expected), tojson(noProjectResults));
-
- const count = coll.count({"a.b": {$ne: null}});
- assert.eq(count, expected.length);
+ assert(resultsEq(noProjectResults,
+ [
+ {_id: "a_subobject_b_not_null", a: {b: "hi"}},
+ {_id: "a_double_array", a: [[]]},
+ {_id: "a_empty_array", a: []},
+ {_id: "a_object_array_no_b_nulls", a: [{b: 1}, {b: 3}, {b: "string"}]},
+ {_id: "a_value_array_all_nulls", a: [null, null]},
+ {_id: "a_value_array_no_nulls", a: [1, "string", 4]},
+ {_id: "a_value_array_with_null", a: [1, "string", null, 4]},
+ {_id: "a_value_array_with_undefined", a: [1, "string", undefined, 4]}
+ ]),
+ tojson(noProjectResults));
const projectResults = coll.find({"a.b": {$ne: null}}, projectToOnlyADotB).toArray();
assert(resultsEq(projectResults,
@@ -612,9 +554,6 @@ function testNullSemantics(coll) {
{_id: "a_object_array_some_b_missing", a: [{b: 3}, {}]},
];
- const count = coll.count({"a.b": {$in: [null, 75]}});
- assert.eq(count, expected.length);
-
assert(resultsEq(noProjectResults, expected), noProjectResults);
}());
@@ -636,9 +575,6 @@ function testNullSemantics(coll) {
{_id: "a_object_array_some_b_missing", a: [{b: 3}, {}]},
];
- const count = coll.count({$or: [{"a.b": null}, {"a.b": 75}]});
- assert.eq(count, expected.length);
-
assert(resultsEq(noProjectResults, expected), noProjectResults);
}());
@@ -659,9 +595,6 @@ function testNullSemantics(coll) {
assert(resultsEq(noProjectResults, expected), noProjectResults);
- const count = coll.count({"a.b": {$nin: [null, 75]}});
- assert.eq(count, expected.length);
-
const projectResults = coll.find(query, projectToOnlyA).toArray();
assert(resultsEq(projectResults, extractAValues(expected)), projectResults);
}());
@@ -680,9 +613,6 @@ function testNullSemantics(coll) {
{_id: "a_value_array_with_undefined", a: [1, "string", undefined, 4]},
];
- const count = coll.count({"a.b": {$nin: [null, /^str.*/]}});
- assert.eq(count, expected.length);
-
assert(resultsEq(noProjectResults, expected), noProjectResults);
const projectResults = coll.find(query, projectToOnlyA).toArray();
@@ -695,9 +625,6 @@ function testNullSemantics(coll) {
let results = coll.find({"a.b": {$elemMatch: {$eq: null}}}).toArray();
assert(resultsEq(results, []), tojson(results));
- const count = coll.count({"a.b": {$elemMatch: {$eq: null}}});
- assert.eq(count, 0);
-
results = coll.find({"a.b": {$elemMatch: {$ne: null}}}).toArray();
assert(resultsEq(results, []), tojson(results));
}());
@@ -715,9 +642,6 @@ function testNullSemantics(coll) {
];
assert(resultsEq(noProjectResults, expectedEqualToNull), tojson(noProjectResults));
- const count = coll.count({a: {$elemMatch: {b: {$eq: null}}}});
- assert.eq(count, expectedEqualToNull.length);
-
let projectResults =
coll.find({a: {$elemMatch: {b: {$eq: null}}}}, projectToOnlyADotB).toArray();
assert(resultsEq(projectResults,
diff --git a/jstests/core/opcounters_write_cmd.js b/jstests/core/opcounters_write_cmd.js
index 9e0d68cd928..6f74185e9f7 100644
--- a/jstests/core/opcounters_write_cmd.js
+++ b/jstests/core/opcounters_write_cmd.js
@@ -2,7 +2,6 @@
// @tags: [
// uses_multiple_connections,
// assumes_standalone_mongod,
-// inspects_command_opcounters,
// ]
// Legacy write mode test also available at jstests/gle.
diff --git a/jstests/core/operation_latency_histogram.js b/jstests/core/operation_latency_histogram.js
index 3597a064429..c87d5bfe20b 100644
--- a/jstests/core/operation_latency_histogram.js
+++ b/jstests/core/operation_latency_histogram.js
@@ -12,7 +12,6 @@
// # Tenant migrations passthrough suites automatically retry operations on TenantMigrationAborted
// # errors.
// tenant_migration_incompatible,
-// uses_compact
// ]
//
diff --git a/jstests/core/or_to_in.js b/jstests/core/or_to_in.js
index 5d3c745dc95..3c9cacfbcdf 100644
--- a/jstests/core/or_to_in.js
+++ b/jstests/core/or_to_in.js
@@ -25,25 +25,19 @@ function compareValues(v1, v2) {
}
// Check that 'expectedQuery' and 'actualQuery' have the same plans, and produce the same result.
-function assertEquivPlanAndResult(expectedQuery, actualQuery, supportWithCollation) {
+function assertEquivPlanAndResult(expectedQuery, actualQuery) {
const expectedExplain = coll.find(expectedQuery).explain("queryPlanner");
const actualExplain = coll.find(actualQuery).explain("queryPlanner");
// The queries must be rewritten into the same form.
- assert.docEq(expectedExplain.queryPlanner.parsedQuery, actualExplain.queryPlanner.parsedQuery);
+ assert.docEq(expectedExplain.parsedQuery, actualExplain.parsedQuery);
- // We are always running these queries to ensure a server crash is not triggered.
- // TODO SERVER-72450: Add appropriate assertions for the output.
- const expectedExplainCollation =
+ // Check if the test queries produce the same plans with collations
+ const expectedExplainColln =
coll.find(expectedQuery).sort({f1: 1}).collation({locale: 'en_US'}).explain("queryPlanner");
- const actualExplainCollation =
+ const actualExplainColln =
coll.find(actualQuery).sort({f1: 1}).collation({locale: 'en_US'}).explain("queryPlanner");
-
- if (supportWithCollation) {
- // Check if the test queries produce the same plans with collations.
- assert.docEq(expectedExplainCollation.queryPlanner.parsedQuery,
- actualExplainCollation.queryPlanner.parsedQuery);
- }
+ assert.docEq(expectedExplainColln.parsedQuery, actualExplainColln.parsedQuery);
// Make sure both queries have the same access plan.
const expectedPlan = getWinningPlan(expectedExplain.queryPlanner);
@@ -57,13 +51,12 @@ function assertEquivPlanAndResult(expectedQuery, actualQuery, supportWithCollati
const actualRes = coll.find(actualQuery).toArray();
assert(arrayEq(expectedRes, actualRes, false, compareValues),
`expected=${expectedRes}, actual=${actualRes}`);
-
// also with collation
- const expectedResCollation =
+ const expectedResColln =
coll.find(expectedQuery).sort({f1: 1}).collation({locale: 'en_US'}).toArray();
- const actualResCollation =
+ const actualResColln =
coll.find(actualQuery).sort({f1: 1}).collation({locale: 'en_US'}).toArray();
- assert(arrayEq(expectedResCollation, actualResCollation, false, compareValues),
+ assert(arrayEq(expectedResColln, actualResColln, false, compareValues),
`expected=${expectedRes}, actual=${actualRes}`);
}
@@ -101,71 +94,32 @@ assert.commandWorked(coll.insert(data));
// Pairs of queries where the first one is expressed via OR (which is supposed to be
// rewritten as IN), and the second one is an equivalent query using IN.
-//
-// The third element of the array is optional, if present, implies that the rewrite is not
-// supported when there is a collation involved.
-//
-// TODO SERVER-72450: Remove or update this logic related to collation, and enforce stronger
-// assertions.
const positiveTestQueries = [
- {actualQuery: {$or: [{f1: 5}, {f1: 3}, {f1: 7}]}, expectedQuery: {f1: {$in: [7, 3, 5]}}},
- {
- actualQuery: {$or: [{f1: {$eq: 5}}, {f1: {$eq: 3}}, {f1: {$eq: 7}}]},
- expectedQuery: {f1: {$in: [7, 3, 5]}}
- },
- {
- actualQuery: {$or: [{f1: 42}, {f1: NaN}, {f1: 99}]},
- expectedQuery: {f1: {$in: [42, NaN, 99]}}
- },
- {
- actualQuery: {$or: [{f1: /^x/}, {f1: "ab"}]},
- expectedQuery: {f1: {$in: [/^x/, "ab"]}},
- cannotRewriteWithCollation: true
- },
- {
- actualQuery: {$or: [{f1: /^x/}, {f1: "^a"}]},
- expectedQuery: {f1: {$in: [/^x/, "^a"]}},
- cannotRewriteWithCollation: true
- },
- {
- actualQuery: {$or: [{f1: 42}, {f1: null}, {f1: 99}]},
- expectedQuery: {f1: {$in: [42, 99, null]}}
- },
- {
- actualQuery: {$or: [{f1: 1}, {f2: 9}, {f1: 99}]},
- expectedQuery: {$or: [{f2: 9}, {f1: {$in: [1, 99]}}]}
- },
- {
- actualQuery: {$or: [{f1: {$regex: /^x/}}, {f1: {$regex: /ab/}}]},
- expectedQuery: {f1: {$in: [/^x/, /ab/]}}
- },
- {
- actualQuery:
- {$and: [{$or: [{f1: 7}, {f1: 3}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
- expectedQuery: {$and: [{f1: {$in: [7, 3, 5]}}, {f1: {$in: [1, 2, 3]}}]}
- },
- {
- actualQuery:
- {$or: [{$or: [{f1: 7}, {f1: 3}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
- expectedQuery: {$or: [{f1: {$in: [7, 3, 5]}}, {f1: {$in: [1, 2, 3]}}]}
- },
- {
- actualQuery:
- {$or: [{$and: [{f1: 7}, {f2: 7}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
- expectedQuery: {$or: [{$and: [{f1: 7}, {f2: 7}, {f1: 5}]}, {f1: {$in: [1, 2, 3]}}]},
- },
- {
- actualQuery: {$or: [{f2: [32, 52]}, {f2: [42, [13, 11]]}]},
- expectedQuery: {f2: {$in: [[32, 52], [42, [13, 11]]]}}
- },
- {actualQuery: {$or: [{f2: 52}, {f2: 13}]}, expectedQuery: {f2: {$in: [52, 13]}}},
- {actualQuery: {$or: [{f2: [11]}, {f2: [23]}]}, expectedQuery: {f2: {$in: [[11], [23]]}}},
- {actualQuery: {$or: [{f1: 42}, {f1: null}]}, expectedQuery: {f1: {$in: [42, null]}}},
- {
- actualQuery: {$or: [{f1: "a"}, {f1: "b"}, {f1: /c/}]},
- expectedQuery: {f1: {$in: ["a", "b", /c/]}},
- cannotRewriteWithCollation: true
- },
+ [{$or: [{f1: 5}, {f1: 3}, {f1: 7}]}, {f1: {$in: [7, 3, 5]}}],
+ [{$or: [{f1: {$eq: 5}}, {f1: {$eq: 3}}, {f1: {$eq: 7}}]}, {f1: {$in: [7, 3, 5]}}],
+ [{$or: [{f1: 42}, {f1: NaN}, {f1: 99}]}, {f1: {$in: [42, NaN, 99]}}],
+ [{$or: [{f1: /^x/}, {f1: "ab"}]}, {f1: {$in: [/^x/, "ab"]}}],
+ [{$or: [{f1: /^x/}, {f1: "^a"}]}, {f1: {$in: [/^x/, "^a"]}}],
+ [{$or: [{f1: 42}, {f1: null}, {f1: 99}]}, {f1: {$in: [42, 99, null]}}],
+ [{$or: [{f1: 1}, {f2: 9}, {f1: 99}]}, {$or: [{f2: 9}, {f1: {$in: [1, 99]}}]}],
+ [{$or: [{f1: {$regex: /^x/}}, {f1: {$regex: /ab/}}]}, {f1: {$in: [/^x/, /ab/]}}],
+ [
+ {$and: [{$or: [{f1: 7}, {f1: 3}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
+ {$and: [{f1: {$in: [7, 3, 5]}}, {f1: {$in: [1, 2, 3]}}]}
+ ],
+ [
+ {$or: [{$or: [{f1: 7}, {f1: 3}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
+ {$or: [{f1: {$in: [7, 3, 5]}}, {f1: {$in: [1, 2, 3]}}]}
+ ],
+ [
+ {$or: [{$and: [{f1: 7}, {f2: 7}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
+ {$or: [{$and: [{f1: 7}, {f2: 7}, {f1: 5}]}, {f1: {$in: [1, 2, 3]}}]},
+ ],
+ [{$or: [{f2: [32, 52]}, {f2: [42, [13, 11]]}]}, {f2: {$in: [[32, 52], [42, [13, 11]]]}}],
+ [{$or: [{f2: 52}, {f2: 13}]}, {f2: {$in: [52, 13]}}],
+ [{$or: [{f2: [11]}, {f2: [23]}]}, {f2: {$in: [[11], [23]]}}],
+ [{$or: [{f1: 42}, {f1: null}]}, {f1: {$in: [42, null]}}],
+ [{$or: [{f1: "a"}, {f1: "b"}, {f1: /c/}]}, {f1: {$in: ["a", "b", /c/]}}],
];
// These $or queries should not be rewritten into $in because of different semantics.
@@ -179,27 +133,22 @@ for (const query of negativeTestQueries) {
assertOrNotRewrittenToIn(query);
}
-function testOrToIn(queries, usesCollation) {
+function testOrToIn(queries) {
for (const queryPair of queries) {
- if (usesCollation && queryPair.cannotRewriteWithCollation) {
- continue;
- }
- assertEquivPlanAndResult(
- queryPair.actualQuery, queryPair.expectedQuery, !queryPair.cannotRewriteWithCollation);
+ assertEquivPlanAndResult(queryPair[0], queryPair[1]);
}
}
-testOrToIn(positiveTestQueries, false /* usesCollation */); // test without indexes
+testOrToIn(positiveTestQueries); // test without indexes
assert.commandWorked(coll.createIndex({f1: 1}));
-testOrToIn(positiveTestQueries, false /* usesCollation */); // single index
+testOrToIn(positiveTestQueries); // single index
assert.commandWorked(coll.createIndex({f2: 1}));
assert.commandWorked(coll.createIndex({f1: 1, f2: 1}));
-testOrToIn(positiveTestQueries,
- false /* usesCollation */); // three indexes, requires multiplanning
+testOrToIn(positiveTestQueries); // three indexes, requires multiplanning
// Test with a collection that has a collation, and that collation is the same as the query
// collation
@@ -207,12 +156,12 @@ coll.drop();
assert.commandWorked(db.createCollection("orToIn", {collation: {locale: 'en_US'}}));
coll = db.orToIn;
assert.commandWorked(coll.insert(data));
-testOrToIn(positiveTestQueries, true /* usesCollation */);
+testOrToIn(positiveTestQueries);
// Test with a collection that has a collation, and that collation is different from the query
// collation
coll.drop();
assert.commandWorked(db.createCollection("orToIn", {collation: {locale: 'de'}}));
coll = db.orToIn;
assert.commandWorked(coll.insert(data));
-testOrToIn(positiveTestQueries, true /* usesCollation */);
+testOrToIn(positiveTestQueries);
}());
diff --git a/jstests/core/partialFilterExpression_with_geoWithin.js b/jstests/core/partialFilterExpression_with_geoWithin.js
index f3ce022636b..794a6b4cae9 100644
--- a/jstests/core/partialFilterExpression_with_geoWithin.js
+++ b/jstests/core/partialFilterExpression_with_geoWithin.js
@@ -1,14 +1,15 @@
// @tags: [requires_non_retryable_writes, requires_fcv_51]
load("jstests/libs/analyze_plan.js");
-load("jstests/libs/feature_flag_util.js");
-
(function() {
"use strict";
const coll = db.partialFilterExpression_with_geoWithin;
coll.drop();
-if (FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+const isFeatureEnabled = db.adminCommand({getParameter: 1, featureFlagTimeseriesMetricIndexes: 1})
+ .featureFlagTimeseriesMetricIndexes.value;
+
+if (isFeatureEnabled) {
// The first collection ensures our changes work with a variety of types (polygon, point,
// linestring) and guarantees some shapes are not inside our index (bigPoly20).
var bigPoly20 = {
@@ -166,4 +167,4 @@ if (FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
// inside the limits of our polygon (or in other words, inside the UWS of Manhattan ).
assert.eq(results.length, 1);
}
-})();
+})(); \ No newline at end of file
diff --git a/jstests/core/partial_index_logical.js b/jstests/core/partial_index_logical.js
deleted file mode 100644
index 3d0c332e57a..00000000000
--- a/jstests/core/partial_index_logical.js
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * Test the planners ability to distinguish parameterized queries in the presence of a partial index
- * containing logical expressions ($and, $or).
- *
- * @tags: [
- * # Since the plan cache is per-node state, this test assumes that all operations are happening
- * # against the same mongod.
- * assumes_read_preference_unchanged,
- * assumes_read_concern_unchanged,
- * does_not_support_stepdowns,
- * # If all chunks are moved off of a shard, it can cause the plan cache to miss commands.
- * assumes_balancer_off,
- * assumes_unsharded_collection,
- * # Plan cache state is node-local and will not get migrated alongside tenant data.
- * tenant_migration_incompatible,
- * requires_fcv_60,
- * no_selinux,
- * ]
- */
-(function() {
-"use strict";
-
-load("jstests/libs/analyze_plan.js"); // For getPlanCacheKeyFromShape.
-
-const coll = db[jsTestName()];
-coll.drop();
-(function partialIndexMixedFields() {
- coll.drop();
-
- // Create enough competing indexes such that a query is eligible for caching (single plan
- // queries are not cached).
- assert.commandWorked(coll.createIndex({num: 1}, {partialFilterExpression: {num: 5, foo: 6}}));
- assert.commandWorked(coll.createIndex({num: -1}));
- assert.commandWorked(coll.createIndex({num: -1, not_num: 1}));
-
- assert.commandWorked(coll.insert([
- {_id: 0, num: 5, foo: 6},
- {_id: 1, num: 5, foo: 7},
- ]));
-
- // Run a query which is eligible to use the {num: 1} index as it is covered by the partial
- // filter expression.
- assert.eq(coll.find({num: 5, foo: 6}).itcount(), 1);
- assert.eq(coll.find({num: 5, foo: 6}).itcount(), 1);
- const matchingKey =
- getPlanCacheKeyFromShape({query: {num: 5, foo: 6}, collection: coll, db: db});
- assert.eq(
- 1,
- coll.aggregate([{$planCacheStats: {}}, {$match: {planCacheKey: matchingKey}}]).itcount());
-
- // This query should not be eligible for the {num: 1} index despite the path 'num' being
- // compatible (per the plan cache key encoding).
- assert.eq(1, coll.find({num: 5, foo: 7}).itcount());
- const nonCoveredKey =
- getPlanCacheKeyFromShape({query: {num: 5, foo: 7}, collection: coll, db: db});
- assert.eq(
- 1,
- coll.aggregate([{$planCacheStats: {}}, {$match: {planCacheKey: nonCoveredKey}}]).itcount());
-
- // Sanity check that the generated keys are different due to the index compatibility.
- assert.neq(nonCoveredKey, matchingKey);
-})();
-
-(function partialIndexDisjunction() {
- coll.drop();
-
- // Create enough competing indexes such that a query is eligible for caching (single plan
- // queries are not cached).
- assert.commandWorked(coll.createIndex(
- {num: 1},
- {partialFilterExpression: {$or: [{num: {$exists: true}}, {num: {$type: 'number'}}]}}));
- assert.commandWorked(coll.createIndex({num: -1}));
- assert.commandWorked(coll.createIndex({num: -1, not_num: 1}));
-
- assert.commandWorked(coll.insert([
- {_id: 0},
- {_id: 1, num: null},
- {_id: 2, num: 5},
- ]));
-
- // Run a query which is eligible to use the {num: 1} index as it is covered by the partial
- // filter expression.
- assert.eq(coll.find({num: 5}).itcount(), 1);
- assert.eq(coll.find({num: 5}).itcount(), 1);
- const numericKey = getPlanCacheKeyFromShape({query: {num: 5}, collection: coll, db: db});
- assert.eq(
- 1, coll.aggregate([{$planCacheStats: {}}, {$match: {planCacheKey: numericKey}}]).itcount());
-
- // The plan for the query above should now be in the cache and active. Now execute a query with
- // a very similar shape, however the predicate parameters are not satisfied by the partial
- // filter expression. This is because {num: null} should match both explicit null as well as
- // missing values (the latter are not indexed).
- assert.eq(2, coll.find({num: null}).itcount());
- const nullKey = getPlanCacheKeyFromShape({query: {num: null}, collection: coll, db: db});
- assert.eq(1,
- coll.aggregate([{$planCacheStats: {}}, {$match: {planCacheKey: nullKey}}]).itcount());
-
- // Sanity check that the generated keys are different due to the index compatibility.
- assert.neq(nullKey, numericKey);
-})();
-
-(function partialIndexDisjunctionWithCollation() {
- coll.drop();
-
- const caseInsensitive = {locale: "en_US", strength: 2};
-
- // Create enough competing indexes such that a query is eligible for caching (single plan
- // queries are not cached).
- assert.commandWorked(coll.createIndex({a: 1}, {
- partialFilterExpression: {$or: [{a: {$gt: 0}}, {a: {$gt: ""}}]},
- collation: caseInsensitive,
- }));
- assert.commandWorked(coll.createIndex({a: -1}));
- assert.commandWorked(coll.createIndex({a: -1, b: 1}));
-
- assert.commandWorked(coll.insert([
- {_id: 0, a: "some"},
- {_id: 1, a: "string"},
- ]));
-
- // Populate the plan cache for a query which is eligible for the partial index. This is true
- // without an explicit collation because the query text does not contain any string comparisons.
- assert.eq(coll.aggregate({$match: {a: {$in: [1, 3]}}}).itcount(), 0);
- assert.eq(coll.aggregate({$match: {a: {$in: [1, 3]}}}).itcount(), 0);
- const simpleCollationKey =
- getPlanCacheKeyFromShape({query: {a: {$in: [1, 3]}}, collection: coll, db: db});
- assert.eq(1,
- coll.aggregate([{$planCacheStats: {}}, {$match: {planCacheKey: simpleCollationKey}}])
- .itcount());
-
- // A collation-sensitive query should _not_ use the cached plan since the default simple
- // collation does not match the collation on the index.
- assert.eq(coll.aggregate({$match: {a: {$in: ["a", "Some"]}}}).itcount(), 0);
- assert.eq(coll.aggregate({$match: {a: {$in: ["a", "Some"]}}}).itcount(), 0);
- const collationSensitiveKey =
- getPlanCacheKeyFromShape({query: {a: {$in: ["a", "Some"]}}, collection: coll, db: db});
- assert.eq(
- 1,
- coll.aggregate([{$planCacheStats: {}}, {$match: {planCacheKey: collationSensitiveKey}}])
- .itcount());
-
- // Sanity check that the generated keys are different due to the collation and index
- // compatibility.
- assert.neq(collationSensitiveKey, simpleCollationKey);
-})();
-
-(function partialIndexConjunction() {
- coll.drop();
-
- // Create enough competing indexes such that a query is eligible for caching (single plan
- // queries are not cached).
- assert.commandWorked(
- coll.createIndex({num: 1}, {partialFilterExpression: {num: {$gt: 0, $lt: 10}}}));
- assert.commandWorked(coll.createIndex({num: -1}));
- assert.commandWorked(coll.createIndex({num: -1, not_num: 1}));
-
- assert.commandWorked(coll.insert([
- {_id: 0},
- {_id: 1, num: 1},
- {_id: 2, num: 11},
- ]));
-
- // Run a query which is eligible to use the {num: 1} index as it is covered by the partial
- // filter expression.
- assert.eq(coll.find({num: {$gt: 0, $lt: 10}}).itcount(), 1);
- assert.eq(coll.find({num: {$gt: 0, $lt: 10}}).itcount(), 1);
- const validKey =
- getPlanCacheKeyFromShape({query: {num: {$gt: 0, $lt: 10}}, collection: coll, db: db});
- assert.eq(
- 1, coll.aggregate([{$planCacheStats: {}}, {$match: {planCacheKey: validKey}}]).itcount());
-
- // The plan for the query above should now be in the cache and active. Now execute a query with
- // a very similar shape, however the predicate parameters are not satisfied by the partial
- // filter expression.
- assert.eq(2, coll.find({num: {$gt: 0, $lt: 12}}).itcount());
-})();
-})();
diff --git a/jstests/core/plan_cache_list_plans.js b/jstests/core/plan_cache_list_plans.js
index 802a25635e0..ca571a9e39e 100644
--- a/jstests/core/plan_cache_list_plans.js
+++ b/jstests/core/plan_cache_list_plans.js
@@ -12,7 +12,6 @@
// assumes_unsharded_collection,
// does_not_support_stepdowns,
// inspects_whether_plan_cache_entry_is_active,
-// references_foreign_collection,
// ]
(function() {
diff --git a/jstests/core/plan_cache_stats_shard_and_host.js b/jstests/core/plan_cache_stats_shard_and_host.js
index 0e19786e8f6..e81dcd60692 100644
--- a/jstests/core/plan_cache_stats_shard_and_host.js
+++ b/jstests/core/plan_cache_stats_shard_and_host.js
@@ -5,14 +5,12 @@
// assumes_balancer_off,
// assumes_read_concern_unchanged,
// assumes_read_preference_unchanged,
-// does_not_support_stepdowns,
-// requires_fcv_60,
+// does_not_support_stepdowns
// ]
(function() {
"use strict";
load("jstests/libs/fixture_helpers.js"); // For 'FixtureHelpers'.
-load('jstests/libs/analyze_plan.js'); // For getPlanCacheKeyFromExplain().
const coll = db.plan_cache_stats_shard_and_host;
coll.drop();
@@ -24,20 +22,8 @@ assert.commandWorked(coll.createIndex({b: 1}));
assert.commandWorked(coll.insert({a: 2, b: 3}));
assert.eq(1, coll.find({a: 2, b: 3}).itcount());
-const explain = coll.find({a: 2, b: 3}).explain();
-const planCacheKey = getPlanCacheKeyFromExplain(explain, db);
-
-function filterPlanCacheEntriesByKey(planCacheKey, planCacheContents) {
- let filteredPlanCacheEntries = [];
- for (const entry of planCacheContents) {
- if (entry.planCacheKey === planCacheKey) {
- filteredPlanCacheEntries.push(entry);
- }
- }
- return filteredPlanCacheEntries;
-}
-
-let planCacheContents = filterPlanCacheEntriesByKey(planCacheKey, planCache.list());
+// List the contents of the plan cache for the collection.
+let planCacheContents = planCache.list();
// We expect every shard that has a chunk for the collection to have produced a plan cache entry.
assert.eq(
@@ -59,16 +45,11 @@ for (const entry of planCacheContents) {
// shard/host. As a future improvement, we should return plan cache information from every host in
// every shard. But for now, we use regular host targeting to choose a particular host in each
// shard.
-planCacheContents = filterPlanCacheEntriesByKey(
- planCacheKey, planCache.list([{$group: {_id: "$shard", count: {$sum: 1}}}]));
-
+planCacheContents = planCache.list([{$group: {_id: "$shard", count: {$sum: 1}}}]);
for (const entry of planCacheContents) {
assert.eq(entry.count, 1, entry);
}
-
-planCacheContents = filterPlanCacheEntriesByKey(
- planCacheKey, planCache.list([{$group: {_id: "$host", count: {$sum: 1}}}]));
-
+planCacheContents = planCache.list([{$group: {_id: "$host", count: {$sum: 1}}}]);
for (const entry of planCacheContents) {
assert.eq(entry.count, 1, entry);
}
@@ -76,5 +57,5 @@ for (const entry of planCacheContents) {
// Clear the plan cache and verify that attempting to list the plan cache now returns an empty
// array.
coll.getPlanCache().clear();
-assert.eq([], filterPlanCacheEntriesByKey(planCacheKey, planCache.list()));
+assert.eq([], planCache.list());
}());
diff --git a/jstests/core/profile_agg.js b/jstests/core/profile_agg.js
index b1ce28dd696..d6611fa98ab 100644
--- a/jstests/core/profile_agg.js
+++ b/jstests/core/profile_agg.js
@@ -1,7 +1,6 @@
// @tags: [
// does_not_support_stepdowns,
// requires_profiling,
-// references_foreign_collection,
// ]
// Confirms that profiled aggregation execution contains all expected metrics with proper values.
diff --git a/jstests/core/profile_update.js b/jstests/core/profile_update.js
index 8a3e680da60..f9c9d91738c 100644
--- a/jstests/core/profile_update.js
+++ b/jstests/core/profile_update.js
@@ -98,9 +98,12 @@ assert.commandWorked(coll.update({_id: "new value", a: 4}, {$inc: {b: 1}}, {upse
profileObj = getLatestProfilerEntry(testDB);
const collectionIsClustered = ClusteredCollectionUtil.areAllCollectionsClustered(db.getMongo());
-const expectedPlan = collectionIsClustered ? "CLUSTERED_IXSCAN" : "IXSCAN { _id: 1 }";
-const expectedKeysExamined = 0;
-const expectedDocsExamined = collectionIsClustered ? 1 : 0;
+// A clustered collection has no actual index on _id. While a bounded collection scan is in
+// principle an efficient option, the query planner only defaults to collection scan if no suitable
+// index is available.
+const expectedPlan = collectionIsClustered ? "IXSCAN { a: 1 }" : "IXSCAN { _id: 1 }";
+const expectedKeysExamined = collectionIsClustered ? 1 : 0;
+const expectedDocsExamined = expectedKeysExamined;
const expectedKeysInserted = collectionIsClustered ? 1 : 2;
assert.eq(profileObj.command,
@@ -144,17 +147,13 @@ for (var i = 0; i < indices.length; i++) {
const profileObj = profiles[i];
const index = indices[i];
- let expectedPlan = "IXSCAN { _id: 1 }";
- let expectedKeysExamined = 0;
- let expectedDocsExamined = 0;
- let expectedKeysInserted = 2;
-
- if (collectionIsClustered) {
- expectedPlan = "CLUSTERED_IXSCAN";
- expectedKeysExamined = 0;
- expectedDocsExamined = (i + 1 == indices.length) ? 1 : 2;
- expectedKeysInserted = 1;
- }
+ // A clustered collection has no actual index on _id. While a bounded collection scan is in
+ // principle an efficient option, the query planner only defaults to collection scan if no
+ // suitable index is available.
+ const expectedPlan = collectionIsClustered ? "IXSCAN { a: 1 }" : "IXSCAN { _id: 1 }";
+ const expectedKeysExamined = collectionIsClustered ? 1 : 0;
+ const expectedDocsExamined = expectedKeysExamined;
+ const expectedKeysInserted = collectionIsClustered ? 1 : 2;
assert.eq(
profileObj.command,
diff --git a/jstests/core/project_with_collation.js b/jstests/core/project_with_collation.js
deleted file mode 100644
index 33d7a5cc2a2..00000000000
--- a/jstests/core/project_with_collation.js
+++ /dev/null
@@ -1,185 +0,0 @@
-// Tests to verify the behavior of find command's project in the presence of collation.
-//
-// @tags: [
-// assumes_no_implicit_collection_creation_after_drop,
-// requires_fcv_60,
-// no_selinux,
-// ]
-
-(function() {
-'use strict';
-
-const collation = {
- locale: "en_US",
- strength: 2
-};
-const withCollationCollName = jsTestName() + "_collation";
-const noCollationCollName = jsTestName() + "_noCollation";
-
-function setupCollection(withCollation) {
- const insertCollName = withCollation ? withCollationCollName : noCollationCollName;
- db[insertCollName].drop();
- if (withCollation) {
- assert.commandWorked(db.createCollection(insertCollName, {collation: withCollation}));
- }
-
- const insertColl = db[insertCollName];
- assert.commandWorked(insertColl.insert(
- {_id: 0, str: "a", array: [{str: "b"}, {str: "A"}, {str: "B"}, {str: "a"}]}));
- assert.commandWorked(insertColl.insert({_id: 1, str: "a", elemMatch: [{str: "A"}, "ignored"]}));
- assert.commandWorked(insertColl.insert({_id: 2, str: "A", elemMatch: ["ignored", {str: "a"}]}));
- assert.commandWorked(insertColl.insert({_id: 3, str: "B"}));
-
- return insertColl;
-}
-
-function runQueryWithCollation(testColl, collationToUse) {
- let findCmd =
- testColl.find({str: 'A', elemMatch: {$elemMatch: {str: "a"}}}, {_id: 1, 'elemMatch.$': 1});
- if (collationToUse) {
- findCmd = findCmd.collation(collationToUse);
- }
- const elemMatchOutput = findCmd.toArray();
- assert.sameMembers(elemMatchOutput,
- [{_id: 1, elemMatch: [{str: "A"}]}, {_id: 2, elemMatch: [{str: "a"}]}]);
-
- findCmd =
- testColl.find({str: 'A'}, {sortedArray: {$sortArray: {input: "$array", sortBy: {str: 1}}}});
- if (collationToUse) {
- findCmd = findCmd.collation(collationToUse);
- }
- const sortArrayOutput = findCmd.toArray();
- assert.sameMembers(sortArrayOutput, [
- {_id: 0, sortedArray: [{str: "A"}, {str: "a"}, {str: "b"}, {str: "B"}]},
- {_id: 1, sortedArray: null},
- {_id: 2, sortedArray: null}
- ]);
-
- const findAndUpdateOutput = testColl.findAndModify({
- query: {_id: 1, str: 'A', elemMatch: {$elemMatch: {str: "a"}}},
- fields: {_id: 1, 'elemMatch.$': 1, updated: 1},
- update: {$set: {updated: true}},
- collation: collationToUse
- });
- assert.docEq(findAndUpdateOutput, {_id: 1, elemMatch: [{str: "A"}]});
-
- const findAndUpdateWithSortArrayOutput = testColl.findAndModify({
- query: {_id: 0, str: 'A'},
- fields: {_id: 1, str: 1, sortedArray: {$sortArray: {input: "$array", sortBy: {str: 1}}}},
- update: {$set: {updated: true}},
- collation: collationToUse,
- new: true
- });
- assert.docEq(findAndUpdateWithSortArrayOutput,
- {_id: 0, str: "a", sortedArray: [{str: "A"}, {str: "a"}, {str: "b"}, {str: "B"}]});
-
- const findAndRemoveOutput = testColl.findAndModify({
- query: {_id: 1, str: 'A', elemMatch: {$elemMatch: {str: "a"}}},
- fields: {_id: 1, 'elemMatch.$': 1, updated: 1},
- remove: true,
- collation: collationToUse,
- });
- assert.docEq(findAndRemoveOutput, {_id: 1, elemMatch: [{str: "A"}], updated: true});
-
- const findAndRemoveWithSortArrayOutput = testColl.findAndModify({
- query: {_id: 0, str: 'A'},
- fields: {_id: 1, str: 1, sortedArray: {$sortArray: {input: "$array", sortBy: {str: 1}}}},
- remove: true,
- collation: collationToUse
- });
- assert.docEq(findAndRemoveWithSortArrayOutput,
- {_id: 0, str: "a", sortedArray: [{str: "A"}, {str: "a"}, {str: "b"}, {str: "B"}]});
-}
-
-// The output for the below two tests should not depend on the collection level collation.
-let collWithCollation = setupCollection({locale: "en_US"});
-runQueryWithCollation(collWithCollation, collation);
-
-let noCollationColl = setupCollection(false);
-runQueryWithCollation(noCollationColl, collation);
-
-// Tests to verify that the projection code inherits collection level collation in the absence of
-// query level collation.
-collWithCollation = setupCollection(collation);
-runQueryWithCollation(collWithCollation, null);
-
-// The output of this should not depend on the collection level collation and simple collation
-// should be applied always.
-function queryWithSimpleCollation(testColl) {
- const elemMatchOutput =
- testColl.find({str: 'A', elemMatch: {$elemMatch: {str: "a"}}}, {_id: 1, 'elemMatch.$': 1})
- .collation({locale: "simple"})
- .toArray();
- assert.sameMembers(elemMatchOutput, [{_id: 2, elemMatch: [{str: "a"}]}]);
-
- const sortArrayOutput =
- testColl.find({str: 'a'}, {sortedArray: {$sortArray: {input: "$array", sortBy: {str: 1}}}})
- .collation({locale: "simple"})
- .toArray();
- assert.sameMembers(sortArrayOutput, [
- {_id: 0, sortedArray: [{str: "A"}, {str: "B"}, {str: "a"}, {str: "b"}]},
- {_id: 1, sortedArray: null}
- ]);
-
- // Test findAndModify command with 'update'. Ensure that simple collation is always honored.
- const findAndUpdateOutput = testColl.findAndModify({
- query: {str: 'A', elemMatch: {$elemMatch: {str: "a"}}},
- fields: {_id: 1, 'elemMatch.$': 1, updated: 1},
- update: {$set: {updated: true}},
- collation: {locale: "simple"}
- });
- assert.docEq(findAndUpdateOutput, {_id: 2, elemMatch: [{str: "a"}]});
-
- const findAndUpdateWithSortArrayOutput = testColl.findAndModify({
- query: {_id: 0, str: 'a'},
- fields: {_id: 1, str: 1, sortedArray: {$sortArray: {input: "$array", sortBy: {str: 1}}}},
- update: {$set: {updated: true}},
- collation: {locale: "simple"},
- new: true
- });
- assert.docEq(findAndUpdateWithSortArrayOutput,
- {_id: 0, str: "a", sortedArray: [{str: "A"}, {str: "B"}, {str: "a"}, {str: "b"}]});
-
- // Test findAndModify command with remove:true. Ensure that simple collation is always honored.
- const findAndRemoveOutput = testColl.findAndModify({
- query: {_id: 2, str: 'A', elemMatch: {$elemMatch: {str: "a"}}},
- fields: {_id: 1, 'elemMatch.$': 1, updated: 1},
- remove: true,
- collation: {locale: "simple"},
- });
- assert.docEq(findAndRemoveOutput, {_id: 2, elemMatch: [{str: "a"}], updated: true});
-
- const findAndRemoveWithSortArrayOutput = testColl.findAndModify({
- query: {_id: 0, str: 'a'},
- fields: {_id: 1, str: 1, sortedArray: {$sortArray: {input: "$array", sortBy: {str: 1}}}},
- remove: true,
- collation: {locale: "simple"}
- });
- assert.docEq(findAndRemoveWithSortArrayOutput,
- {_id: 0, str: "a", sortedArray: [{str: "A"}, {str: "B"}, {str: "a"}, {str: "b"}]});
-}
-
-noCollationColl = setupCollection(false);
-queryWithSimpleCollation(noCollationColl);
-
-collWithCollation = setupCollection(collation);
-queryWithSimpleCollation(collWithCollation);
-
-// Test with views.
-(function viewWithCollation() {
- collWithCollation = setupCollection(collation);
- db[jsTestName() + "_view"].drop();
- assert.commandWorked(
- db.createView(jsTestName() + "_view", withCollationCollName, [], {collation: collation}));
- const viewColl = db[jsTestName() + "_view"];
-
- const sortArrayOutput =
- viewColl.find({str: 'A'}, {sortedArray: {$sortArray: {input: "$array", sortBy: {str: 1}}}})
- .toArray();
- assert.sameMembers(sortArrayOutput, [
- {_id: 0, sortedArray: [{str: "A"}, {str: "a"}, {str: "b"}, {str: "B"}]},
- {_id: 1, sortedArray: null},
- {_id: 2, sortedArray: null}
- ]);
-})();
-})();
diff --git a/jstests/core/query/internal_strip_invalid_assignment.js b/jstests/core/query/internal_strip_invalid_assignment.js
deleted file mode 100644
index b8868c6e951..00000000000
--- a/jstests/core/query/internal_strip_invalid_assignment.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Test that '$_internalSchemaAllElemMatchFromIndex' does not use an index, and does not trigger an
- * assertion failure when we strip its index assignment from special indexes.
- *
- * Originally intended to reproduce SERVER-82717.
- *
- * @tags: [
- * # Explain command does not support read concerns other than local.
- * assumes_read_concern_local,
- * ]
- */
-(function() {
-load('jstests/libs/analyze_plan.js'); // for planHasStage
-
-const coll = db.getCollection(jsTestName());
-
-assert.commandWorked(coll.createIndex({a: 1, foo: '2dsphere'}));
-assert.commandWorked(coll.createIndex({a: 1, '$**': 'text'}));
-assert.commandWorked(coll.createIndex({a: 1}, {partialFilterExpression: {foo: 123}}));
-
-const query = {
- "$or": [
- // Has to be the same field.
- {"a": 1},
- {
- "a": {
- // Checks that ALL elements of an array match this predicate.
- // An index on {a: 1, ...} doesn't help, because:
- // - If it's multikey, each index entry only tells us one array-element, while
- // the predicate needs to check all elements.
- // - If it's non-multikey, the predicate is trivially false, because it expects
- // an array.
- "$_internalSchemaAllElemMatchFromIndex": [
- // Number of elements to skip.
- NumberLong(0),
- // Predicate to run on each element.
- {"i": {"$regex": "b"}},
- ]
- }
- }
- ]
-};
-const explain = coll.find(query).explain();
-assert(planHasStage(db, explain, "COLLSCAN"), explain);
-})();
diff --git a/jstests/core/rename_collection_system_db.js b/jstests/core/rename_collection_system_db.js
index e9e166914c0..8d46ad27a04 100644
--- a/jstests/core/rename_collection_system_db.js
+++ b/jstests/core/rename_collection_system_db.js
@@ -16,9 +16,10 @@ systemUsers.drop();
coll.drop();
coll.insert({});
-// system.foo and system.users aren't in the allowlist so they can't be renamed to or from
+// system.foo isn't in the allowlist so it can't be renamed to or from
assert.commandFailed(coll.renameCollection(systemFoo.getName()));
assert.commandFailed(systemFoo.renameCollection(coll.getName()));
-assert.commandFailed(coll.renameCollection(systemUsers.getName()));
-assert.commandFailed(systemUsers.renameCollection(coll.getName()));
+// system.users is allowlisted so these should work
+assert.commandWorked(coll.renameCollection(systemUsers.getName()));
+assert.commandWorked(systemUsers.renameCollection(coll.getName()));
diff --git a/jstests/core/rename_collection_view.js b/jstests/core/rename_collection_view.js
deleted file mode 100644
index eda30c4e2fb..00000000000
--- a/jstests/core/rename_collection_view.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Basic test around rename collection involving views
- */
-
-(function() {
-"use strict";
-
-const collNamePrefix = "rename_collection_view_collection";
-const viewNamePrefix = "rename_collection_view_view";
-let collCounter = 0;
-let viewCounter = 0;
-
-function getNewCollName() {
- return collNamePrefix + collCounter++;
-}
-
-function getNewColl() {
- let coll = db[getNewCollName()];
- coll.drop();
- assert.commandWorked(db[coll.getName()].insert({_id: 1}));
- return coll;
-}
-
-/**
- * Drops a view and then recreates against an underlying collection. Handle the case for those
- * suites where the test runs multiple times against the same cluster/replicaset instance and view
- * already exists
- */
-function getNewView(collName) {
- // new view with empty filter
- const viewName = viewNamePrefix + viewCounter++;
- db.runCommand({drop: viewName});
- assert.commandWorked(db.createView(viewName, collName, []));
- return db[viewName];
-}
-
-jsTest.log(
- "Rename existing view should fail with CommandNotSupportedOnView indipendently on the target type (view or collection)");
-{
- const srcColl = getNewColl();
- const srcView = getNewView(srcColl.getName());
- const dstColl = getNewColl();
- const dstView = getNewView(dstColl.getName());
-
- assert.commandFailedWithCode(
- db.adminCommand({renameCollection: srcView.getFullName(), to: dstColl.getFullName()}),
- ErrorCodes.CommandNotSupportedOnView,
- "rename view to existing collection should fail with CommandNotSupportedOnView");
-
- assert.commandFailedWithCode(
- db.adminCommand(
- {renameCollection: srcView.getFullName(), to: dstColl.getFullName(), dropTarget: true}),
- ErrorCodes.CommandNotSupportedOnView,
- "rename view to existing collection should fail with CommandNotSupportedOnView even if dropTarget is true");
-
- assert.commandFailedWithCode(
- db.adminCommand({renameCollection: srcView.getFullName(), to: dstView.getFullName()}),
- ErrorCodes.CommandNotSupportedOnView,
- "rename view to existing view should fail with CommandNotSupportedOnView");
-
- assert.commandFailedWithCode(
- db.adminCommand(
- {renameCollection: srcView.getFullName(), to: dstView.getFullName(), dropTarget: true}),
- ErrorCodes.CommandNotSupportedOnView,
- "rename view to existing view should fail with CommandNotSupportedOnView even if dropTarget is true");
-}
-
-jsTest.log("Rename coll to existing view should fail with NamespaceExists");
-{
- const srcColl = getNewColl();
- const dstColl = getNewColl();
-
- const dstView = getNewView(dstColl.getName());
-
- assert.commandFailedWithCode(
- db.adminCommand({renameCollection: srcColl.getFullName(), to: dstView.getFullName()}),
- ErrorCodes.NamespaceExists,
- "rename collection to existing view should fail with NamespaceExists");
-
- assert.commandFailedWithCode(
- db.adminCommand(
- {renameCollection: srcColl.getFullName(), to: dstView.getFullName(), dropTarget: true}),
- ErrorCodes.NamespaceExists,
- "rename collection to existing view should fail with NamespaceExists even if dropTarget is true");
-}
-})();
diff --git a/jstests/core/shell_connection_strings.js b/jstests/core/shell_connection_strings.js
index bd0646e3647..0cf2f3867d5 100644
--- a/jstests/core/shell_connection_strings.js
+++ b/jstests/core/shell_connection_strings.js
@@ -1,7 +1,6 @@
// Test mongo shell connect strings.
// @tags: [
// uses_multiple_connections,
-// docker_incompatible,
// ]
(function() {
'use strict';
diff --git a/jstests/core/timeseries/bucket_unpacking_with_sort.js b/jstests/core/timeseries/bucket_unpacking_with_sort.js
index 695e94daec9..029697be74a 100644
--- a/jstests/core/timeseries/bucket_unpacking_with_sort.js
+++ b/jstests/core/timeseries/bucket_unpacking_with_sort.js
@@ -17,9 +17,6 @@
* requires_timeseries,
* # Explain of a resolved view must be executed by mongos.
* directly_against_shardsvrs_incompatible,
- * # Time-series hint by index key did not exist in 5.0.
- * # Also, the 5.0 version of this feature does not support reverse collscan.
- * requires_fcv_60,
* ]
*/
(function() {
diff --git a/jstests/core/timeseries/bucket_unpacking_with_sort_extended_range.js b/jstests/core/timeseries/bucket_unpacking_with_sort_extended_range.js
deleted file mode 100644
index e74d1c3e914..00000000000
--- a/jstests/core/timeseries/bucket_unpacking_with_sort_extended_range.js
+++ /dev/null
@@ -1,269 +0,0 @@
-/**
- * Test that sort queries work properly on dates ouside the 32 bit epoch range,
- * [1970-01-01 00:00:00 UTC - 2038-01-29 03:13:07 UTC], when a collection scan is used.
- *
- * @tags: [
- * # Explain of a resolved view must be executed by mongos.
- * directly_against_shardsvrs_incompatible,
- * # This complicates aggregation extraction.
- * do_not_wrap_aggregations_in_facets,
- * # Refusing to run a test that issues an aggregation command with explain because it may
- * # return incomplete results if interrupted by a stepdown.
- * does_not_support_stepdowns,
- * # We need a timeseries collection.
- * requires_timeseries,
- * # Cannot insert into a time-series collection in a multi-document transaction.
- * does_not_support_transactions,
- * # Time-series hint by index key did not exist in 5.0
- * requires_fcv_60,
- * ]
- */
-
-(function() {
-"use strict";
-
-load("jstests/aggregation/extras/utils.js"); // For getExplainedPipelineFromAggregation.
-load("jstests/core/timeseries/libs/timeseries.js");
-load('jstests/libs/analyze_plan.js');
-
-if (!TimeseriesTest.bucketUnpackWithSortEnabled(db.getMongo())) {
- jsTestLog("Skipping test because 'BucketUnpackWithSort' is disabled.");
- return;
-}
-
-const timeFieldName = "t";
-
-// Create unindexed collection
-const coll = db.timeseries_internal_bounded_sort_extended_range;
-const buckets = db['system.buckets.' + coll.getName()];
-coll.drop();
-assert.commandWorked(db.createCollection(coll.getName(), {timeseries: {timeField: 't'}}));
-
-// Create collection indexed on time
-const collIndexed = db.timeseries_internal_bounded_sort_extended_range_with_index;
-const bucketsIndexed = db['system.buckets.' + collIndexed.getName()];
-collIndexed.drop();
-assert.commandWorked(db.createCollection(collIndexed.getName(), {timeseries: {timeField: 't'}}));
-assert.commandWorked(collIndexed.createIndex({'t': 1}));
-
-jsTestLog(collIndexed.getIndexes());
-jsTestLog(bucketsIndexed.getIndexes());
-
-function numShards() {
- return db.getSiblingDB('config').shards.count();
-}
-for (const collection of [buckets, bucketsIndexed]) {
- if (FixtureHelpers.isSharded(collection) && numShards() >= 2) {
- // Split and move data to create an interesting scenario: we have some data on each shard,
- // but all the extended-range data is on a non-primary shard. This means view resolution is
- // unaware of the extended-range data, because that happens on the primary shard.
-
- const shards = db.getSiblingDB('config').shards.find().toArray();
- const [shardName0, shardName1] = shards.map(doc => doc._id);
-
- assert.commandWorked(db.adminCommand({movePrimary: db.getName(), to: shardName0}));
- const collName = collection.getFullName();
- // Our example data has documents between 2000-2003, and these dates are non-wrapping.
- // So this goes on the primary shard, and everything else goes on the non-primary.
- assert.commandWorked(sh.splitAt(collName, {'control.min.t': ISODate('2000-01-01')}));
- assert.commandWorked(sh.splitAt(collName, {'control.min.t': ISODate('2003-01-01')}));
- assert.commandWorked(
- sh.moveChunk(collName, {'control.min.t': ISODate('1969-01-01')}, shardName1));
- assert.commandWorked(
- sh.moveChunk(collName, {'control.min.t': ISODate('2000-01-01')}, shardName0));
- assert.commandWorked(
- sh.moveChunk(collName, {'control.min.t': ISODate('2003-01-01')}, shardName1));
- }
-}
-
-const intervalMillis = 60000;
-function insertBucket(start) {
- jsTestLog("Inserting bucket starting with " + Date(start).toString());
-
- const batchSize = 1000;
-
- const batch =
- Array.from({length: batchSize}, (_, j) => ({t: new Date(start + j * intervalMillis)}));
-
- assert.commandWorked(coll.insert(batch));
- assert.commandWorked(collIndexed.insert(batch));
-}
-
-// Insert some data. We'll insert 5 buckets in each range, with values < 0,
-// values between 0 and FFFFFFFF(unsigned), and values > FFFFFFFF. It turns out, however,
-// that Javascript's Date doesn't handle dates beyond 2039 either, so we rely on lower dates
-// to test for unexpected behavior.
-function insertDocuments() {
- // We want to choose the underflow and overflow lower bits in such a way that we
- // encourage wrong results when the upper bytes are removed.
- const underflowMin = new Date("1969-01-01").getTime(); // Year before the 32 bit epoch
- const normalMin = new Date("2002-01-01").getTime(); // Middle of the 32 bit epoch
-
- insertBucket(underflowMin);
-
- var numBatches = 5;
-
- const batchOffset = Math.floor(intervalMillis / (numBatches + 1));
- for (let i = 0; i < numBatches; ++i) {
- const start = normalMin + i * batchOffset;
- insertBucket(start);
- }
- assert.gt(buckets.aggregate([{$count: 'n'}]).next().n, 1, 'Expected more than one bucket');
-}
-
-insertDocuments();
-
-const unpackStage = getAggPlanStages(coll.explain().aggregate(), '$_internalUnpackBucket')[0];
-
-function assertSorted(result, ascending) {
- let prev = ascending ? {t: -Infinity} : {t: Infinity};
- for (const doc of result) {
- if (ascending) {
- assert.lt(+prev.t,
- +doc.t,
- 'Found two docs not in ascending time order: ' + tojson({prev, doc}));
- } else {
- assert.gt(+prev.t,
- +doc.t,
- 'Found two docs not in descending time order: ' + tojson({prev, doc}));
- }
-
- prev = doc;
- }
-}
-
-function checkAgainstReferenceBoundedSortUnexpected(
- collection, reference, pipeline, hint, sortOrder) {
- const options = hint ? {hint: hint} : {};
-
- const bucket = db['system.buckets.' + coll.getName()];
-
- const plan = collection.explain().aggregate(pipeline, options);
- if (FixtureHelpers.isSharded(buckets) && numShards() >= 2) {
- // With a sharded collection, some shards might not have any extended-range data,
- // so they might still use $_internalBoundedSort. But we know at least one
- // shard has extended-range data, so we know at least one shard has to
- // use a blocking sort.
- const bounded = getAggPlanStages(plan, "$_internalBoundedSort");
- const blocking = getAggPlanStages(plan, "$sort");
- assert.gt(blocking.length, 0, {bounded, blocking, plan});
- assert.lt(bounded.length,
- FixtureHelpers.numberOfShardsForCollection(buckets),
- {bounded, blocking, plan});
- } else {
- const stages = getAggPlanStages(plan, "$_internalBoundedSort");
- assert.eq([], stages, plan);
- }
-
- const opt = collection.aggregate(pipeline, options).toArray();
- assertSorted(opt, sortOrder);
-
- assert.eq(reference.length, opt.length);
- for (var i = 0; i < opt.length; ++i) {
- assert.docEq(reference[i], opt[i]);
- }
-}
-
-function checkAgainstReferenceBoundedSortExpected(
- collection, reference, pipeline, hint, sortOrder) {
- const options = hint ? {hint: hint} : {};
-
- const plan = collection.explain().aggregate(pipeline, options);
- const stages = getAggPlanStages(plan, "$_internalBoundedSort");
- assert.neq([], stages, plan);
-
- const opt = collection.aggregate(pipeline, options).toArray();
- assertSorted(opt, sortOrder);
-
- assert.eq(reference.length, opt.length);
- for (var i = 0; i < opt.length; ++i) {
- assert.docEq(reference[i], opt[i]);
- }
-}
-
-function runTest(ascending) {
- const reference = buckets
- .aggregate([
- unpackStage,
- {$_internalInhibitOptimization: {}},
- {$sort: {t: ascending ? 1 : -1}},
- ])
- .toArray();
- assertSorted(reference, ascending);
-
- // Check plan using collection scan
- checkAgainstReferenceBoundedSortUnexpected(coll,
- reference,
- [
- {$sort: {t: ascending ? 1 : -1}},
- ],
- {},
- ascending);
-
- // Check plan using hinted collection scan
- checkAgainstReferenceBoundedSortUnexpected(coll,
- reference,
- [
- {$sort: {t: ascending ? 1 : -1}},
- ],
- {"$natural": ascending ? 1 : -1},
- ascending);
-
- const referenceIndexed = bucketsIndexed
- .aggregate([
- unpackStage,
- {$_internalInhibitOptimization: {}},
- {$sort: {t: ascending ? 1 : -1}},
- ])
- .toArray();
- assertSorted(referenceIndexed, ascending);
-
- // Check plan using index scan. If we've inserted a date before 1-1-1970, we round the min
- // up towards 1970, rather then down, which has the effect of increasing the control.min.t.
- // This means the minimum time in the bucket is likely to be lower than indicated and thus,
- // actual dates may be out of order relative to what's indicated by the bucket bounds.
- checkAgainstReferenceBoundedSortUnexpected(collIndexed,
- referenceIndexed,
- [
- {$sort: {t: ascending ? 1 : -1}},
- ],
- {},
- ascending);
-
- // Check plan using hinted index scan
- checkAgainstReferenceBoundedSortUnexpected(collIndexed,
- referenceIndexed,
- [
- {$sort: {t: ascending ? 1 : -1}},
- ],
- {"t": 1},
- ascending);
-
- // Check plan using hinted collection scan
- checkAgainstReferenceBoundedSortUnexpected(collIndexed,
- referenceIndexed,
- [
- {$sort: {t: ascending ? 1 : -1}},
- ],
- {"$natural": ascending ? 1 : -1},
- ascending);
-
- // The workaround in all cases is to create a reverse index on the time field, though
- // it's necessary to force use of the reversed index.
- const reverseIdxName = "reverseIdx";
- collIndexed.createIndex({t: -1}, {name: reverseIdxName});
-
- checkAgainstReferenceBoundedSortExpected(collIndexed,
- referenceIndexed,
- [
- {$sort: {t: ascending ? 1 : -1}},
- ],
- {"t": -1},
- ascending);
-
- collIndexed.dropIndex(reverseIdxName);
-}
-
-runTest(false); // descending
-runTest(true); // ascending
-})();
diff --git a/jstests/core/timeseries/bucket_unpacking_with_sort_plan_cache.js b/jstests/core/timeseries/bucket_unpacking_with_sort_plan_cache.js
index e69a8d7a860..25e1c99312e 100644
--- a/jstests/core/timeseries/bucket_unpacking_with_sort_plan_cache.js
+++ b/jstests/core/timeseries/bucket_unpacking_with_sort_plan_cache.js
@@ -21,8 +21,6 @@
* directly_against_shardsvrs_incompatible,
* # We use the profiler to get info in order to force replanning.
* requires_profiling,
- * # The 5.0 version of this feature does not support reverse collscan.
- * requires_fcv_60,
* ]
*/
(function() {
diff --git a/jstests/core/timeseries/libs/timeseries.js b/jstests/core/timeseries/libs/timeseries.js
index 540e0bcea55..ea8d71c87a1 100644
--- a/jstests/core/timeseries/libs/timeseries.js
+++ b/jstests/core/timeseries/libs/timeseries.js
@@ -11,20 +11,6 @@ var TimeseriesTest = class {
return FeatureFlagUtil.isEnabled(conn, "TimeseriesBucketCompression");
}
- static bucketsMayHaveMixedSchemaData(coll) {
- const catalog = coll.aggregate([{$listCatalog: {}}]).toArray()[0];
- const tsMixedSchemaOptionNewFormat = catalog.md.options.storageEngine &&
- catalog.md.options.storageEngine.wiredTiger &&
- catalog.md.options.storageEngine.wiredTiger.configString;
- // TODO SERVER-92533 Simplify once SERVER-91195 is backported to all supported branches
- if (tsMixedSchemaOptionNewFormat !== undefined) {
- return tsMixedSchemaOptionNewFormat ==
- "app_metadata=(timeseriesBucketsMayHaveMixedSchemaData=true)";
- } else {
- return catalog.md.timeseriesBucketsMayHaveMixedSchemaData;
- }
- }
-
/**
* Returns whether time-series updates and deletes are supported.
*/
@@ -66,16 +52,9 @@ var TimeseriesTest = class {
}
static bucketUnpackWithSortEnabled(conn) {
- const resp50 = conn.adminCommand({getParameter: 1, featureFlagBucketUnpackWithSort50: 1});
- const resp = conn.adminCommand({getParameter: 1, featureFlagBucketUnpackWithSort: 1});
- assert(Boolean(resp50.ok) ^ Boolean(resp.ok),
- `Expected exactly one of these feature flags to exist: ${tojson(resp50)} vs ${
- tojson(resp)}`);
- if (resp50.ok) {
- return assert.commandWorked(resp50).featureFlagBucketUnpackWithSort50.value;
- } else {
- return assert.commandWorked(resp).featureFlagBucketUnpackWithSort.value;
- }
+ return assert
+ .commandWorked(conn.adminCommand({getParameter: 1, featureFlagBucketUnpackWithSort: 1}))
+ .featureFlagBucketUnpackWithSort.value;
}
/**
@@ -220,7 +199,7 @@ var TimeseriesTest = class {
static ensureDataIsDistributedIfSharded(coll, splitPointDate) {
const db = coll.getDB();
- const buckets = db[this.getBucketsCollName(coll.getName())];
+ const buckets = db["system.buckets." + coll.getName()];
if (FixtureHelpers.isSharded(buckets)) {
const timeFieldName =
db.getCollectionInfos({name: coll.getName()})[0].options.timeseries.timeField;
@@ -269,8 +248,4 @@ var TimeseriesTest = class {
}
}
}
-
- static getBucketsCollName(collName) {
- return `system.buckets.${collName}`;
- }
};
diff --git a/jstests/core/timeseries/nondefault_collation.js b/jstests/core/timeseries/nondefault_collation.js
index 01f9b8c635c..3ff1c63d330 100644
--- a/jstests/core/timeseries/nondefault_collation.js
+++ b/jstests/core/timeseries/nondefault_collation.js
@@ -1,13 +1,8 @@
/**
- * Correctness tests for TS collections with collation that might not match the explicit collation,
- * specified in the query.
- *
- * Queries on timeseries attempt various optimizations to avoid unpacking of buckets. These rely on
- * the meta field and the control data (currently, min and max), computed for each bucket.
- * Collection's collation might affect the computed control values.
+ * Test ensures that users can specify non-default collation when querying on time-series
+ * collections.
*
* @tags: [
- * assumes_unsharded_collection,
* requires_non_retryable_writes,
* requires_pipeline_optimization,
* requires_getmore,
@@ -26,221 +21,123 @@ load("jstests/libs/analyze_plan.js");
const coll = db.timeseries_nondefault_collation;
const bucketsColl = db.getCollection('system.buckets.' + coll.getName());
+coll.drop(); // implicitly drops bucketsColl.
+
+const timeFieldName = 'time';
+const metaFieldName = 'meta';
+
const numericOrdering = {
- locale: "en_US",
- numericOrdering: true,
- strength: 1 // case and diacritics ignored
+ collation: {locale: "en_US", numericOrdering: true}
};
+
const caseSensitive = {
- locale: "en_US",
- strength: 1,
- caseLevel: true
+ collation: {locale: "en_US", strength: 1, caseLevel: true, numericOrdering: true}
};
+
const diacriticSensitive = {
- locale: "en_US",
- strength: 2,
- caseLevel: false
+ collation: {locale: "en_US", strength: 2}
};
-const insensitive = {
- locale: "en_US",
+
+const englishCollation = {
+ locale: 'en',
strength: 1
};
-// Find on meta field isn't different from a find on any other view, but let's check it anyway.
-(function testFind_MetaField() {
- coll.drop();
-
- assert.commandWorked(db.createCollection(
- coll.getName(),
- {timeseries: {timeField: 'time', metaField: 'meta'}, collation: numericOrdering}));
- assert.contains(bucketsColl.getName(), db.getCollectionNames());
-
- assert.commandWorked(coll.insert({time: ISODate(), meta: "1", value: 42}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: "10", value: 42}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: "5", value: 42}));
-
- // Use the collection's collation with numeric ordering.
- let res1 = coll.find({meta: {$gt: "4"}});
- assert.eq(2, res1.itcount(), res1.toArray()); // should match "5" and "10"
-
- // Use explicit collation with lexicographic ordering.
- let res2 = coll.find({meta: {$gt: "4"}}).collation(insensitive);
- assert.eq(1, res2.itcount(), res2.toArray()); // should match only "5"
-}());
-
-// For the measurement fields each bucket computes additional "control values", such as min/max and
-// might use them to avoid unpacking.
-(function testFind_MeasurementField() {
- coll.drop();
-
- assert.commandWorked(db.createCollection(
- coll.getName(),
- {timeseries: {timeField: 'time', metaField: 'meta'}, collation: numericOrdering}));
- assert.contains(bucketsColl.getName(), db.getCollectionNames());
-
- // The 'numericOrdering' on the collection means that the max of the bucket with the three docs
- // below is "10" (while the lexicographic max is "5").
- assert.commandWorked(coll.insert({time: ISODate(), meta: 42, value: "1"}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: 42, value: "10"}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: 42, value: "5"}));
-
- // A query with default collation would use the bucket's min/max and find the matches. We are
- // not checking the unpacking optimizations here as it's not a concern of collation per se.
- let res1 = coll.find({value: {$gt: "4"}});
- assert.eq(2, res1.itcount(), res1.toArray()); // should match "5" and "10"
-
- // If a query with 'insensitive' collation, which doesn't do numeric ordering, used the bucket's
- // min/max it would miss the bucket. Check, that it doesn't.
- let res2 = coll.find({value: {$gt: "4"}}).collation(insensitive);
- assert.eq(1, res2.itcount(), res2.toArray()); // should match only "5"
-}());
-
-(function testFind_OnlyQueryHasCollation() {
- coll.drop();
-
- assert.commandWorked(
- db.createCollection(coll.getName(), {timeseries: {timeField: 'time', metaField: 'meta'}}));
-
- // This should generate a bucket with control.min.value = 'C' and control.max.value = 'c'.
- assert.commandWorked(coll.insert({time: ISODate(), meta: 42, value: "C"}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: 42, value: "b"}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: 42, value: "c"}));
-
- // A query with default collation would use the bucket's min/max and find the two matches.
- const resWithNoCollation = coll.find({value: {$lt: "c"}});
- assert.eq(2,
- resWithNoCollation.itcount(),
- resWithNoCollation.toArray()); // should match "C" and "b".
-
- // If a query with 'insensitive' collation used the bucket's min/max it would miss the bucket.
- // Check, that it doesn't.
- const resWithCollation_find = coll.find({value: {$lt: "c"}}).collation(insensitive);
- assert.eq(1,
- resWithCollation_find.itcount(),
- resWithCollation_find.toArray()); // should match only "b".
-
- // Run the same test with aggregate command.
- const resWithCollation_agg =
- coll.aggregate([{$match: {value: {$lt: "c"}}}], {collation: insensitive}).toArray();
- assert.eq(1, resWithCollation_agg.length, resWithCollation_agg);
-}());
-
-(function testAgg_GroupByMetaField() {
- coll.drop();
-
- assert.commandWorked(db.createCollection(
- coll.getName(),
- {timeseries: {timeField: 'time', metaField: 'meta'}, collation: numericOrdering}));
- assert.contains(bucketsColl.getName(), db.getCollectionNames());
-
- assert.commandWorked(coll.insert({time: ISODate(), meta: "1", val: 1}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: "5", val: 1}));
-
- // Using collection's collation with numeric ordering.
- let res1 =
- coll.aggregate([{$bucket: {groupBy: "$meta", boundaries: ["1", "10", "50"]}}]).toArray();
- assert.eq(1, res1.length);
- assert.eq({_id: "1", count: 2}, res1[0]);
-
- // Using explicit collation with lexicographic ordering.
- let res2 = coll.aggregate([{$bucket: {groupBy: "$meta", boundaries: ["1", "10", "50"]}}],
- {collation: insensitive})
- .toArray();
- assert.eq(2, res2.length);
- assert.eq({_id: "1", count: 1}, res2[0]); // "1" goes here
- assert.eq({_id: "10", count: 1}, res2[1]); // "5" goes here
-}());
-
-(function testAgg_GroupByMeasurementField() {
- coll.drop();
-
- assert.commandWorked(db.createCollection(
- coll.getName(),
- {timeseries: {timeField: 'time', metaField: 'meta'}, collation: insensitive}));
- assert.contains(bucketsColl.getName(), db.getCollectionNames());
-
- // Cause two different buckets with various case/diacritics in each for the measurement 'name'.
- assert.commandWorked(coll.insert({time: ISODate(), meta: "a", name: 'A'}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: "a", name: 'a'}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: "a", name: 'á'}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: "b", name: 'A'}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: "b", name: 'a'}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: "b", name: 'ä'}));
-
- // Test with the collection's collation, which is case and diacritic insensitive.
- assert.eq(1, coll.aggregate([{$sortByCount: "$name"}]).itcount());
-
- // Test with explicit collation that is different from the collection's.
- assert.eq(2, coll.aggregate([{$sortByCount: "$name"}], {collation: caseSensitive}).itcount());
- assert.eq(3,
- coll.aggregate([{$sortByCount: "$name"}], {collation: diacriticSensitive}).itcount());
-}());
-
-// For $group queries that would put whole buckets into the same group, it might be possible to
-// avoid unpacking if the information the group is computing is exposed in the control data of each
-// bucket. Currently, we only do this optimization for min/max with the meta as the group key.
-(function testAgg_MinMaxOptimization() {
- coll.drop();
-
- assert.commandWorked(db.createCollection(
- coll.getName(),
- {timeseries: {timeField: 'time', metaField: 'meta'}, collation: numericOrdering}));
- assert.contains(bucketsColl.getName(), db.getCollectionNames());
-
- // These two docs will be placed in the same bucket, and the max for the bucket will be computed
- // using collection's collation, that is, it should be "10".
- assert.commandWorked(coll.insert({time: ISODate(), meta: 42, val: "10"}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: 42, val: "5"}));
-
- // Let's check our understanding of what happens with the bucketing as otherwise the tests below
- // won't be testing what we think they are.
- let buckets = bucketsColl.find().toArray();
- assert.eq(1, buckets.length, "All docs should be placed into the same bucket");
- assert.eq("10", buckets[0].control.max.val, "Computed max control for 'val' measurement");
-
- // Use the collection's collation with numeric ordering.
- let res1 = coll.aggregate([{$group: {_id: "$meta", v: {$max: "$val"}}}]).toArray();
- assert.eq("10", res1[0].v, "max val in numeric ordering per the collection's collation");
-
- // Use the collection's collation with lexicographic ordering.
- let res2 =
- coll.aggregate([{$group: {_id: "$meta", v: {$max: "$val"}}}], {collation: insensitive})
- .toArray();
- assert.eq("5", res2[0].v, "max val in lexicographic ordering per the query collation");
-}());
-
-(function testFind_IndexWithDifferentCollation() {
- coll.drop();
-
- assert.commandWorked(db.createCollection(
- coll.getName(),
- {timeseries: {timeField: 'time', metaField: 'meta'}, collation: diacriticSensitive}));
- assert.contains(bucketsColl.getName(), db.getCollectionNames());
-
- // Create index with a different collation.
- assert.commandWorked(coll.createIndex({meta: 1}, {collation: insensitive}));
-
- // We only check that the correct plan is chosen so the contents of the collection don't matter
- // as long as it's not empty.
- assert.commandWorked(coll.insert({time: ISODate(), meta: 42}));
- assert.commandWorked(coll.insert({time: ISODate(), meta: "the answer"}));
-
- // Queries that don't specify explicit collation should use the collection's default collation
- // which isn't compatible with the index, so the index should NOT be used.
- let query = coll.find({meta: "str"}).explain();
- assert(!aggPlanHasStage(query, "IXSCAN"), query);
-
- // Queries with an explicit collation which isn't compatible with the index, should NOT do
- // index scan.
- query = coll.find({meta: "str"}).collation(caseSensitive).explain();
- assert(!aggPlanHasStage(query, "IXSCAN"), query);
-
- // Queries with the same collation as in the index, should do index scan.
- query = coll.find({meta: "str"}).collation(insensitive).explain();
- assert(aggPlanHasStage(query, "IXSCAN"), query);
+const simpleCollation = {
+ collation: {locale: "simple"}
+};
- // Numeric queries that don't rely on collation should do index scan.
- query = coll.find({meta: 1}).explain();
- assert(aggPlanHasStage(query, "IXSCAN"), query);
-}());
+assert.commandWorked(db.createCollection(coll.getName(), {
+ timeseries: {timeField: timeFieldName, metaField: metaFieldName},
+ collation: englishCollation
+}));
+assert.contains(bucketsColl.getName(), db.getCollectionNames());
+
+assert.commandWorked(
+ coll.insert({[timeFieldName]: ISODate(), [metaFieldName]: "1", name: 'A', name2: "á"}));
+assert.commandWorked(
+ coll.insert({[timeFieldName]: ISODate(), [metaFieldName]: "2", name: 'a', name2: "á"}));
+assert.commandWorked(
+ coll.insert({[timeFieldName]: ISODate(), [metaFieldName]: "5", name: 'A', name2: "á"}));
+assert.commandWorked(
+ coll.insert({[timeFieldName]: ISODate(), [metaFieldName]: "10", name: 'a', name2: "á"}));
+assert.commandWorked(
+ coll.insert({[timeFieldName]: ISODate(), [metaFieldName]: "20", name: 'A', name2: "a"}));
+assert.commandWorked(
+ coll.insert({[timeFieldName]: ISODate(), [metaFieldName]: "50", name: 'B', name2: "a"}));
+assert.commandWorked(
+ coll.insert({[timeFieldName]: ISODate(), [metaFieldName]: "100", name: 'b', name2: "a"}));
+assert.commandWorked(
+ coll.insert({[timeFieldName]: ISODate(), [metaFieldName]: "200", name: 'B', name2: "a"}));
+assert.commandWorked(
+ coll.insert({[timeFieldName]: ISODate(), [metaFieldName]: "500", name: 'b', name2: "a"}));
+
+// Default collation is case and diacretic insensitive.
+assert.eq(2, coll.aggregate([{$sortByCount: "$name"}]).itcount());
+assert.eq(1, coll.aggregate([{$sortByCount: "$name2"}]).itcount());
+
+// Test that a explicit collation different from collection's default passes for a timeseries
+// collection.
+let results =
+ coll.aggregate([{$bucket: {groupBy: "$meta", boundaries: ["1", "10", "100", "1000"]}}],
+ numericOrdering)
+ .toArray();
+assert.eq(3, results.length);
+assert.eq({_id: "1", count: 3}, results[0]);
+assert.eq({_id: "10", count: 3}, results[1]);
+assert.eq({_id: "100", count: 3}, results[2]);
+
+assert.eq(4, coll.aggregate([{$sortByCount: "$name"}], caseSensitive).itcount());
+assert.eq(2, coll.aggregate([{$sortByCount: "$name2"}], diacriticSensitive).itcount());
+
+coll.drop();
+const defaultCollation = {
+ locale: "en",
+ numericOrdering: true,
+ caseLevel: true,
+ strength: 2
+};
+assert.commandWorked(db.createCollection(coll.getName(), {
+ timeseries: {timeField: timeFieldName, metaField: metaFieldName},
+ collation: defaultCollation
+}));
+assert.contains(bucketsColl.getName(), db.getCollectionNames());
+assert.commandWorked(coll.createIndex({[metaFieldName]: 1}, {collation: {locale: "simple"}}));
+
+assert.commandWorked(coll.insert(
+ {[timeFieldName]: ISODate(), [metaFieldName]: 1, name: 'A', name2: "á", value: "1"}));
+assert.commandWorked(coll.insert(
+ {[timeFieldName]: ISODate(), [metaFieldName]: 2, name: 'a', name2: "á", value: "11"}));
+assert.commandWorked(coll.insert(
+ {[timeFieldName]: ISODate(), [metaFieldName]: 1, name: 'A', name2: "á", value: "50"}));
+assert.commandWorked(coll.insert(
+ {[timeFieldName]: ISODate(), [metaFieldName]: 1, name: 'a', name2: "á", value: "100"}));
+assert.commandWorked(coll.insert(
+ {[timeFieldName]: ISODate(), [metaFieldName]: "2", name: 'A', name2: "a", value: "3"}));
+assert.commandWorked(coll.insert(
+ {[timeFieldName]: ISODate(), [metaFieldName]: "5", name: 'B', name2: "a", value: "-100"}));
+assert.commandWorked(coll.insert(
+ {[timeFieldName]: ISODate(), [metaFieldName]: "1", name: 'b', name2: "a", value: "-200"}));
+assert.commandWorked(coll.insert(
+ {[timeFieldName]: ISODate(), [metaFieldName]: "2", name: 'B', name2: "a", value: "1000"}));
+assert.commandWorked(coll.insert(
+ {[timeFieldName]: ISODate(), [metaFieldName]: "5", name: 'b', name2: "a", value: "4"}));
+
+// This collection has been created using non simple collation. The collection was then indexed on
+// its metadata using simple collation. These tests confirm that queries on the indexed field using
+// nondefault (simple) collation use the index. They also confirm that queries that don't involve
+// strings but do use default collation, on indexed fields, also use the index.
+const nonDefaultCollationQuery = coll.find({meta: 2}, {collation: englishCollation}).explain();
+assert(aggPlanHasStage(nonDefaultCollationQuery, "IXSCAN"), nonDefaultCollationQuery);
+
+const simpleNonDefaultCollationQuery = coll.find({meta: 2}, simpleCollation).explain();
+assert(aggPlanHasStage(simpleNonDefaultCollationQuery, "IXSCAN"), simpleNonDefaultCollationQuery);
+
+const defaultCollationQuery = coll.find({meta: 1}, {collation: defaultCollation}).explain();
+assert(aggPlanHasStage(defaultCollationQuery, "IXSCAN"), defaultCollationQuery);
+
+// This test guarantees that the bucket's min/max matches the query's min/max regardless of
+// collation.
+results = coll.find({value: {$gt: "4"}}, simpleCollation);
+assert.eq(4, results.itcount());
}());
diff --git a/jstests/core/timeseries/partialFilterExpression_with_internalBucketGeoWithin.js b/jstests/core/timeseries/partialFilterExpression_with_internalBucketGeoWithin.js
index 61521e7f86e..5be75d79e28 100644
--- a/jstests/core/timeseries/partialFilterExpression_with_internalBucketGeoWithin.js
+++ b/jstests/core/timeseries/partialFilterExpression_with_internalBucketGeoWithin.js
@@ -10,11 +10,12 @@
*/
load("jstests/libs/analyze_plan.js");
-load("jstests/libs/feature_flag_util.js");
load('jstests/noPassthrough/libs/index_build.js');
-
(function() {
-if (FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+const isFeatureEnabled = db.adminCommand({getParameter: 1, featureFlagTimeseriesMetricIndexes: 1})
+ .featureFlagTimeseriesMetricIndexes.value;
+
+if (isFeatureEnabled) {
const timeFieldName = "timestamp";
const coll = db.partialFilterExpression_with_internalBucketGeoWithin;
diff --git a/jstests/core/timeseries/timeseries_bucket_rename.js b/jstests/core/timeseries/timeseries_bucket_rename.js
new file mode 100644
index 00000000000..98a0b73b810
--- /dev/null
+++ b/jstests/core/timeseries/timeseries_bucket_rename.js
@@ -0,0 +1,28 @@
+/**
+ * Tests that a system.buckets collection cannot be renamed.
+ *
+ * @tags: [
+ * does_not_support_stepdowns,
+ * does_not_support_transactions,
+ * requires_getmore,
+ * ]
+ */
+(function() {
+'use strict';
+
+const coll = db.timeseries_bucket_rename;
+const bucketsColl = db.getCollection('system.buckets.' + coll.getName());
+
+const timeFieldName = 'time';
+
+coll.drop();
+assert.commandWorked(db.createCollection(coll.getName(), {timeseries: {timeField: timeFieldName}}));
+assert.contains(bucketsColl.getName(), db.getCollectionNames());
+
+assert.commandFailedWithCode(db.adminCommand({
+ renameCollection: bucketsColl.getFullName(),
+ to: db.getName() + ".otherColl",
+ dropTarget: false
+}),
+ ErrorCodes.IllegalOperation);
+})();
diff --git a/jstests/core/timeseries/timeseries_collection_uuid.js b/jstests/core/timeseries/timeseries_collection_uuid.js
deleted file mode 100644
index 2ba80cc8f16..00000000000
--- a/jstests/core/timeseries/timeseries_collection_uuid.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Tests using the collectionUUID parameter when operating on a time-series collection.
- *
- * @tags: [
- * does_not_support_transactions,
- * requires_fcv_60,
- * requires_timeseries,
- * ]
- */
-
-(function() {
-"use strict";
-
-const dbName = jsTestName();
-const collName = "coll";
-
-const testDB = db.getSiblingDB(dbName);
-testDB.dropDatabase();
-
-assert.commandWorked(
- testDB.createCollection(collName, {timeseries: {timeField: "t", metaField: "m"}}));
-const coll = testDB[collName];
-const bucketsColl = testDB["system.buckets." + collName];
-
-const nonexistentUUID = UUID();
-const bucketsCollUUID = testDB.getCollectionInfos({name: bucketsColl.getName()})[0].info.uuid;
-
-const testInsert = function(uuid, ordered) {
- assert.commandFailedWithCode(testDB.runCommand({
- insert: collName,
- documents: [{t: ISODate()}],
- collectionUUID: uuid,
- ordered: ordered,
- }),
- ErrorCodes.CollectionUUIDMismatch);
-};
-
-testInsert(nonexistentUUID, true);
-testInsert(nonexistentUUID, false);
-testInsert(bucketsCollUUID, true);
-testInsert(bucketsCollUUID, false);
-}());
diff --git a/jstests/core/timeseries/timeseries_collmod.js b/jstests/core/timeseries/timeseries_collmod.js
index 07c9166b632..69fd7dbeb82 100644
--- a/jstests/core/timeseries/timeseries_collmod.js
+++ b/jstests/core/timeseries/timeseries_collmod.js
@@ -19,17 +19,6 @@ assert.commandWorked(
db.createCollection(collName, {timeseries: {timeField: "time", granularity: 'seconds'}}));
assert.commandWorked(coll.createIndex({"time": 1}));
-// Setting prepareUnique should return an error on a time-series collection.
-assert.commandFailedWithCode(
- db.runCommand(
- {"collMod": collName, "index": {"keyPattern": {"time": 1}, "prepareUnique": true}}),
- ErrorCodes.InvalidOptions);
-
-assert.commandFailedWithCode(
- db.runCommand(
- {"collMod": collName, "index": {"keyPattern": {"time": 1}, "prepareUnique": false}}),
- ErrorCodes.InvalidOptions);
-
// Tries to convert a time-series secondary index to TTL index.
assert.commandFailedWithCode(
db.runCommand(
@@ -67,4 +56,4 @@ assert.commandWorked(db.runCommand({"collMod": collName, "expireAfterSeconds": 6
// Successfully sets the granularity for a time-series collection.
assert.commandWorked(
db.runCommand({"collMod": collName, "timeseries": {"granularity": "minutes"}}));
-})();
+})(); \ No newline at end of file
diff --git a/jstests/core/timeseries/timeseries_computed_field.js b/jstests/core/timeseries/timeseries_computed_field.js
deleted file mode 100644
index fab03d1a3b0..00000000000
--- a/jstests/core/timeseries/timeseries_computed_field.js
+++ /dev/null
@@ -1,856 +0,0 @@
-/**
- * Test use of computed fields in aggregations on time series collections.
- * @tags: [
- * requires_timeseries,
- * does_not_support_stepdowns,
- * directly_against_shardsvrs_incompatible,
- * # "Explain of a resolved view must be executed by mongos"
- * directly_against_shardsvrs_incompatible,
- * # Some suites use mixed-binary cluster setup where some nodes might have the flag enabled while
- * # others -- not. For this test we need control over whether the flag is set on the node that
- * # ends up executing the query.
- * assumes_standalone_mongod
- * ]
- */
-load("jstests/core/timeseries/libs/timeseries.js");
-
-TimeseriesTest.run((insert) => {
- const datePrefix = 1680912440;
-
- let coll = db.timeseries_computed_field;
- const bucketsColl = db.getCollection('system.buckets.' + coll.getName());
-
- const timeFieldName = 'time';
- const metaFieldName = 'measurement';
-
- coll.drop();
- assert.commandWorked(db.createCollection(coll.getName(), {
- timeseries: {timeField: timeFieldName, metaField: metaFieldName},
- }));
- assert.contains(bucketsColl.getName(), db.getCollectionNames());
-
- insert(coll, {
- _id: 0,
- [timeFieldName]: new Date(datePrefix + 100), // ISODate("1970-01-20T10:55:12.540Z")
- [metaFieldName]: "cpu",
- topLevelScalar: 123,
- topLevelScalarDouble: 123.8778645,
- topLevelLargeNumber: 12345678912345,
- topLevelArray: [1, 2, 3, 4],
- arrOfObj: [{x: 1}, {x: 2}, {x: 3}, {x: 4}],
- obj: {a: 123},
- length: 0,
- });
- insert(coll, {
- _id: 1,
- [timeFieldName]: new Date(datePrefix + 200), // ISODate("1970-01-20T10:55:12.640Z")
- [metaFieldName]: "cpu",
- topLevelScalar: 456,
- topLevelScalarDouble: 546.76858699,
- topLevelArray: [101, 102, 103, 104],
- arrOfObj: [{x: 101}, {x: 102}, {x: 103}, {x: 104}],
- obj: {a: 456},
- length: 23,
- });
- // Insert a document that will be placed in a different bucket.
- insert(coll, {
- _id: 2,
- [timeFieldName]: new Date(datePrefix + 300),
- [metaFieldName]: "gpu",
- length: -2,
- });
-
- // Computing a field on a dotted path which is an array, then grouping on it. Note that the
- // semantics for setting a computed field on a dotted array path are particularly strange, but
- // should be preserved for backwards compatibility.
- {
- const res = coll.aggregate([
- {$addFields: {"arrOfObj.x": {$trim: {input: "test string"}}}},
- {$match: {topLevelScalar: {$gte: 0}}},
- {$group: {_id: null, max: {$max: "$arrOfObj.x"}}}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].max, ["test string", "test string", "test string", "test string"], res);
- }
-
- {
- const res = coll.aggregate([
- {$addFields: {"arrOfObj.x": {$add: ["$topLevelScalar", 1]}}},
- {$match: {topLevelScalar: {$gte: 0}}},
- {$group: {_id: null, max: {$max: "$arrOfObj.x"}}}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].max, [457, 457, 457, 457], res);
- }
-
- // Computing a field and then filtering by it.
- {
- const res = coll.aggregate([
- {$addFields: {"arrOfObj.x": {$trim: {input: "test string"}}}},
- {$match: {"arrOfObj.x": "test string"}},
- {$group: {_id: null, max: {$max: "$arrOfObj.x"}}}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].max, ["test string", "test string", "test string", "test string"], res);
- }
-
- {
- // Computing a field based on a dotted path which does not traverse arrays.
- const res = coll.aggregate([
- {$addFields: {"computedA": {$add: ["$obj.a", 1]}}},
- // Only one document should have a value where obj.a was 457
- // (456 + 1).
- {$match: {"computedA": 457}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
-
- {
- // Include an unnecessary computed field before counting the number of documents.
- const res = coll.aggregate([{$addFields: {"a": 1}}, {$count: "count"}]).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 3, res);
- }
-
- // mathematical expressions
- {
- let pipeline = [
- {$addFields: {"computedA": {$add: ["$topLevelScalar", 1]}}},
- {$match: {"computedA": 457}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$subtract: ["$topLevelScalar", 1]}}},
- {$match: {"computedA": 455}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$multiply: ["$topLevelScalar", 10]}}},
- {$match: {"computedA": 4560}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$divide: ["$topLevelScalar", 2]}}},
- {$match: {"computedA": 228}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$add: [1, "$topLevelScalar"]}}},
- {$match: {"computedA": 457}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$subtract: [200, "$topLevelScalar"]}}},
- {$match: {"computedA": 77}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$multiply: [10, "$topLevelScalar"]}}},
- {$match: {"computedA": 4560}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$divide: [4560, "$topLevelScalar"]}}},
- {$match: {"computedA": 10}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
-
- {
- let pipeline = [
- {$addFields: {"computedA": {$add: ["$topLevelScalar", "$topLevelScalar"]}}},
- {$match: {"computedA": 912}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$subtract: ["$topLevelScalar", "$topLevelScalar"]}}},
- {$match: {"computedA": 0}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$multiply: ["$topLevelScalar", "$topLevelScalar"]}}},
- {$match: {"computedA": 15129}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$divide: ["$topLevelScalar", "$topLevelScalar"]}}},
- {$match: {"computedA": 1}},
- {$count: "count"}
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- let pipeline = [
- {
- $addFields: {
- "hourDiff": {
- $dateDiff: {
- "startDate": "$time",
- "endDate": new Date("1970-01-21"),
- "unit": "hour"
- }
- }
- }
- },
- {$match: {"hourDiff": {$gte: 12}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "open": {"$first": "$topLevelScalar"},
- }
- }
- ];
-
- assert.docEq([{"_id": {"time": ISODate("1970-01-20T10:55:00Z")}, "open": 123}],
- coll.aggregate(pipeline).toArray());
- }
-
- {
- let pipeline = [
- {$addFields: {"mt": {$multiply: ["$topLevelScalar", 10]}}},
- {$match: {"mt": {$gte: 2000}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "open": {"$first": "$topLevelScalar"},
- }
- }
- ];
-
- assert.docEq([{"_id": {"time": ISODate("1970-01-20T10:55:00Z")}, "open": 456}],
- coll.aggregate(pipeline).toArray());
- }
-
- {
- let pipeline = [
- {
- $addFields: {
- "hourDiff": {
- $dateDiff: {
- "startDate": "$time",
- "endDate": new Date("1970-01-21"),
- "unit": "hour"
- }
- }
- }
- },
- {$match: {$or: [{topLevelScalar: {$gt: 200, $lt: 800}}, {hourDiff: {$gte: 12}}]}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "open": {"$first": "$topLevelScalar"},
- }
- }
- ];
-
- assert.docEq([{"_id": {"time": ISODate("1970-01-20T10:55:00Z")}, "open": 123}],
- coll.aggregate(pipeline).toArray());
- }
-
- {
- // Try a project stage which adds and remove subfields.
- const res = coll.aggregate([
- {$project: {"obj.newField": "$topLevelScalar"}},
- {$project: {"_id": 0, "obj.a": 0}}
- ])
- .toArray();
- assert.eq(res.length, 3, res);
- assert.eq(res[0], {"obj": {"newField": 123}}, res);
- assert.eq(res[1], {"obj": {"newField": 456}}, res);
- assert.eq(res[2], {"obj": {}}, res);
- }
-
- {
- // Try a replaceRoot stage which remove all fields.
- const res = coll.aggregate([
- {$match: {"time": {$gte: new Date(datePrefix + 200)}}},
- {$addFields: {}},
- {$project: {"measurement0": {$floor: "$topLevelScalar"}}},
- {$replaceRoot: {newRoot: {}}}
- ])
- .toArray();
- assert.eq(res.length, 2, res);
- assert.eq(res[0], {}, res);
- assert.eq(res[1], {}, res);
- }
-
- {
- // Try a $match that works on fields that are not projected.
- const res =
- coll.aggregate([
- {$project: {"obj.a": 1}},
- {$match: {$or: [{"topLevelScalar": {$gt: 10}}, {$expr: {$literal: true}}]}},
- {$sort: {_id: 1}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 3, res);
- }
-
- {
- const res = coll.aggregate([{
- "$project": {
- "t": {
- "$dateDiff": {
- "startDate": "$time",
- "endDate": new Date(datePrefix + 150),
- "unit": "millisecond"
- }
- }
- }
- }])
- .toArray();
- assert.eq(res.length, 3, res);
- assert.docEq(res[0], {_id: 0, "t": NumberLong(50)}, res);
- assert.docEq(res[1], {_id: 1, "t": NumberLong(-50)}, res);
- assert.docEq(res[2], {_id: 2, "t": NumberLong(-150)}, res);
- }
-
- {
- const res = coll.aggregate([{
- "$project": {
- "t": {
- "$dateDiff": {
- "startDate": new Date(datePrefix - 10),
- "endDate": "$time",
- "unit": "millisecond"
- }
- }
- }
- }])
- .toArray();
- assert.eq(res.length, 3, res);
- assert.docEq(res[0], {_id: 0, "t": NumberLong(110)}, res);
- assert.docEq(res[1], {_id: 1, "t": NumberLong(210)}, res);
- assert.docEq(res[2], {_id: 2, "t": NumberLong(310)}, res);
- }
-
- {
- const res = coll.aggregate([
- {
- $addFields: {
- "computedField": {
- $dateTrunc: {
- date: "$time",
- unit: "second",
- }
- }
- }
- },
- {$match: {computedField: new Date(datePrefix - 440)}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 3, res);
- }
-
- {
- const res = coll.aggregate([{$match: {topLevelScalar: {$exists: true}}}, {$count: "count"}])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res =
- coll.aggregate([{$match: {topLevelScalar: {$lt: 456}}}, {$count: "count"}]).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
-
- {
- const res =
- coll.aggregate([{$match: {topLevelScalar: {$lte: 456}}}, {$count: "count"}]).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res =
- coll.aggregate([{$match: {topLevelScalar: {$gt: 123}}}, {$count: "count"}]).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
-
- {
- const res =
- coll.aggregate([{$match: {topLevelScalar: {$gte: 123}}}, {$count: "count"}]).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res =
- coll.aggregate([{$match: {topLevelScalar: {$eq: 123}}}, {$count: "count"}]).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
-
- {
- const res =
- coll.aggregate([{$match: {topLevelScalar: {$ne: 123}}}, {$count: "count"}]).toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res = coll.aggregate([
- {
- $match: {
- $or: [
- {"topLevelScalar": 123},
- {"topLevelScalar": 456},
- ]
- }
- },
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res = coll.aggregate([
- {$addFields: {"computedField": {$and: ["$topLevelScalar", true]}}},
- {$match: {computedField: true}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res = coll.aggregate([
- {$addFields: {"computedField": {$and: ["$topLevelScalar", "$obj.a"]}}},
- {$match: {computedField: true}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res = coll.aggregate([
- {$addFields: {"computedField": {$or: ["$topLevelScalar", false]}}},
- {$match: {computedField: true}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res = coll.aggregate([
- {$addFields: {"computedField": {$or: ["$topLevelScalar", "$obj.a"]}}},
- {$match: {computedField: true}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res = coll.aggregate([
- {$addFields: {"computedField": {$not: ["$topLevelScalar"]}}},
- {$match: {computedField: true}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
-
- {
- const res =
- coll.aggregate([
- {$addFields: {"computedField": {$anyElementTrue: [["$topLevelScalar"]]}}},
- {$match: {computedField: true}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 2, res);
- }
-
- {
- const res =
- coll.aggregate([
- {$match: {length: {$ne: 0}}},
- {$set: {"computedA": {$multiply: ["$topLevelScalar", "$topLevelScalar"]}}},
- {$addFields: {"ratio": {$divide: ["$computedA", "$length"]}}},
- {$match: {ratio: {$gt: 0}}},
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0]._id, 1, res);
- }
-
- {
- let pipeline = [
- {$addFields: {"computedA": {$round: ["$topLevelScalarDouble", 2]}}},
- {$match: {"computedA": {$gte: 100}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "value": {$sum: "$computedA"},
- }
- }
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.docEq([{"_id": {"time": ISODate("1970-01-20T10:55:00Z")}, "value": 670.65}], res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$round: ["$topLevelScalarDouble"]}}},
- {$match: {"computedA": {$gte: 100}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "value": {$sum: "$computedA"},
- }
- }
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.docEq([{"_id": {"time": ISODate("1970-01-20T10:55:00Z")}, "value": 671}], res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$round: [2, "$topLevelScalarDouble"]}}},
- {$match: {"computedA": {$gte: 100}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "value": {$sum: "$computedA"},
- }
- }
- ];
-
- assert.throws(() => coll.aggregate(pipeline));
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$round: ["$topLevelScalarDouble", "$topLevelScalar"]}}},
- {$match: {"computedA": {$gte: 100}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "value": {$sum: "$computedA"},
- }
- }
- ];
-
- assert.throws(() => coll.aggregate(pipeline));
- }
-
- {
- let pipeline = [
- {$addFields: {"computedA": {$trunc: ["$topLevelScalarDouble", 2]}}},
- {$match: {"computedA": {$gte: 100}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "value": {$sum: "$computedA"},
- }
- }
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.docEq([{"_id": {"time": ISODate("1970-01-20T10:55:00Z")}, "value": 670.63}], res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$trunc: ["$topLevelScalarDouble"]}}},
- {$match: {"computedA": {$gte: 100}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "value": {$sum: "$computedA"},
- }
- }
- ];
-
- const res = coll.aggregate(pipeline).toArray();
- assert.docEq([{"_id": {"time": ISODate("1970-01-20T10:55:00Z")}, "value": 669}], res);
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$trunc: [2, "$topLevelScalarDouble"]}}},
- {$match: {"computedA": {$gte: 100}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "value": {$sum: "$computedA"},
- }
- }
- ];
-
- assert.throws(() => coll.aggregate(pipeline));
- }
- {
- let pipeline = [
- {$addFields: {"computedA": {$trunc: ["$topLevelScalarDouble", "$topLevelScalar"]}}},
- {$match: {"computedA": {$gte: 100}}},
- {
- $group: {
- "_id": {"time": {"$dateTrunc": {"date": "$time", "unit": "minute"}}},
- "value": {$sum: "$computedA"},
- }
- }
- ];
-
- assert.throws(() => coll.aggregate(pipeline));
- }
-
- {
- let pipeline = [
- {$addFields: {md: {$mod: ["$topLevelScalar", 5]}}},
- {
- $group: {
- "_id": {$dateTrunc: {"date": "$time", "unit": "minute"}},
- "total1": {$sum: "$md"},
- "total2": {$sum: "$topLevelScalar"}
- }
- }
- ];
-
- assert.docEq([{"_id": ISODate("1970-01-20T10:55:00Z"), "total1": 4, "total2": 579}],
- coll.aggregate(pipeline).toArray());
- }
-
- {
- let pipeline = [
- {$addFields: {md: {$mod: [500, "$topLevelScalar"]}}},
- {
- $group: {
- "_id": {$dateTrunc: {"date": "$time", "unit": "minute"}},
- "total1": {$sum: "$md"},
- "total2": {$sum: "$topLevelScalar"}
- }
- }
- ];
-
- assert.docEq([{"_id": ISODate("1970-01-20T10:55:00Z"), "total1": 52, "total2": 579}],
- coll.aggregate(pipeline).toArray());
- }
-
- {
- let pipeline = [
- {$addFields: {md: {$mod: ["$topLevelScalar", "$topLevelScalar"]}}},
- {
- $group: {
- "_id": {$dateTrunc: {"date": "$time", "unit": "minute"}},
- "total1": {$sum: "$md"},
- "total2": {$sum: "$topLevelScalar"}
- }
- }
- ];
-
- assert.docEq([{"_id": ISODate("1970-01-20T10:55:00Z"), "total1": 0, "total2": 579}],
- coll.aggregate(pipeline).toArray());
- }
-
- {
- let pipeline = [
- {$addFields: {md: {$mod: ["$topLevelScalar", 5]}}},
- {$match: {md: {$mod: [4, 1]}}},
- {
- $group: {
- "_id": {$dateTrunc: {"date": "$time", "unit": "minute"}},
- "total1": {$sum: "$md"},
- "total2": {$sum: "$topLevelScalar"}
- }
- }
- ];
-
- assert.docEq([{"_id": ISODate("1970-01-20T10:55:00Z"), "total1": 1, "total2": 456}],
- coll.aggregate(pipeline).toArray());
- }
- {
- let pipeline = [{$match: {topLevelLargeNumber: {$mod: [1, 0]}}}, {$count: "count"}];
-
- const res = coll.aggregate(pipeline).toArray();
-
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
- {
- const res =
- coll.aggregate([
- {
- $addFields: {
- "computedField":
- {$dateAdd: {startDate: "$time", unit: "millisecond", amount: 100}}
- }
- },
- {$match: {computedField: new Date(datePrefix + 400)}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
-
- {
- const res = coll.aggregate([
- {
- $addFields: {
- "computedField": {
- $dateSubtract:
- {startDate: "$time", unit: "millisecond", amount: 100}
- }
- }
- },
- {$match: {computedField: new Date(datePrefix)}},
- {$count: "count"}
- ])
- .toArray();
- assert.eq(res.length, 1, res);
- assert.eq(res[0].count, 1, res);
- }
-
- {
- // Test the case where a computed meta field is computed to missing.
- const res =
- coll.aggregate([{"$project": {"_id": 0, [metaFieldName]: "$$REMOVE"}}]).toArray();
- assert.eq(res.length, coll.count(), res);
- for (let doc of res) {
- assert.eq(doc, {}, res);
- }
- }
-
- {
- // Test the case where a computed meta field is computed to missing because of a project
- // out.
- const res = coll.aggregate([
- {"$project": {[metaFieldName]: 0}},
- {"$project": {[metaFieldName]: "$" + metaFieldName}},
- {$match: {a: 1}}
- ])
- .toArray();
- assert.eq(res.length, 0, res);
- }
-
- {
- // Test the case where a field is projected out and then projected back in.
- const res = coll.aggregate([
- {"$project": {"_id": 0, [metaFieldName]: 1}},
- {"$project": {"_id": 0, [timeFieldName]: "$" + timeFieldName}},
- {"$project": {"_id": 1, [timeFieldName]: 1}}
- ])
- .toArray();
- assert.eq(res.length, coll.count(), res);
- for (let doc of res) {
- assert.eq(doc, {}, res);
- }
- }
-
- {
- // Test the case where a field is projected out and then projected back in.
- const res = coll.aggregate([
- {"$project": {"_id": 0, [metaFieldName]: 1}},
- {"$project": {"_id": 0, [timeFieldName]: 1}}
- ])
- .toArray();
- assert.eq(res.length, coll.count(), res);
- for (let doc of res) {
- assert.eq(doc, {}, res);
- }
- }
-
- {
- // Test the case where a field is projected out and then projected back in.
- const res = coll.aggregate([
- {"$project": {"_id": 0, [metaFieldName]: 0}},
- {"$project": {"_id": 0, [metaFieldName]: 1}},
- {"$project": {"_id": 0, [timeFieldName]: 1}}
- ])
- .toArray();
- assert.eq(res.length, coll.count(), res);
- for (let doc of res) {
- assert.eq(doc, {}, res);
- }
- }
-});
diff --git a/jstests/core/timeseries/timeseries_create_collection.js b/jstests/core/timeseries/timeseries_create_collection.js
index 99616605163..feb2f443d26 100644
--- a/jstests/core/timeseries/timeseries_create_collection.js
+++ b/jstests/core/timeseries/timeseries_create_collection.js
@@ -17,15 +17,6 @@ assert.commandWorked(testDB.dropDatabase());
const timeFieldName = 'time';
const coll = testDB.t;
-// Fails to create a time-series collection with null-embedded timeField or metaField.
-assert.commandFailedWithCode(
- testDB.createCollection(coll.getName(), {timeseries: {timeField: '\0time'}}),
- ErrorCodes.BadValue);
-assert.commandFailedWithCode(
- testDB.createCollection(coll.getName(),
- {timeseries: {timeField: timeFieldName, metaField: 't\0ag'}}),
- ErrorCodes.BadValue);
-
// Create a timeseries collection, listCollection should show view and bucket collection
assert.commandWorked(
testDB.createCollection(coll.getName(), {timeseries: {timeField: timeFieldName}}));
diff --git a/jstests/core/timeseries/timeseries_delete_hint.js b/jstests/core/timeseries/timeseries_delete_hint.js
index 69fb2bc5a91..0facca816e1 100644
--- a/jstests/core/timeseries/timeseries_delete_hint.js
+++ b/jstests/core/timeseries/timeseries_delete_hint.js
@@ -18,11 +18,11 @@
(function() {
"use strict";
+load("jstests/core/timeseries/libs/timeseries.js");
load("jstests/libs/curop_helpers.js");
-load("jstests/libs/feature_flag_util.js");
load('jstests/libs/parallel_shell_helpers.js');
-if (!FeatureFlagUtil.isEnabled(db, "TimeseriesUpdatesAndDeletes")) {
+if (!TimeseriesTest.timeseriesUpdatesAndDeletesEnabled(db.getMongo())) {
jsTestLog("Skipping test because the time-series updates and deletes feature flag is disabled");
return;
}
@@ -71,7 +71,7 @@ const validateDeleteIndex = (docsToInsert,
: assert.commandWorked(
testDB.runCommand({delete: coll.getName(), deletes: deleteQuery}));
assert.eq(res["n"], expectedNRemoved);
- assert.sameMembers(coll.find({}, {_id: 0}).toArray(), expectedRemainingDocs);
+ assert.docEq(coll.find({}, {_id: 0}).toArray(), expectedRemainingDocs);
assert(coll.drop());
},
docsToInsert,
diff --git a/jstests/core/timeseries/timeseries_field_parsed_as_bson.js b/jstests/core/timeseries/timeseries_field_parsed_as_bson.js
deleted file mode 100644
index 70210a90072..00000000000
--- a/jstests/core/timeseries/timeseries_field_parsed_as_bson.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Tests that timeseries timeField is parsed as bson.
- *
- * @tags: [
- * # We need a timeseries collection.
- * requires_timeseries,
- * # Cannot insert into a time-series collection in a multi-document transaction
- * does_not_support_transactions,
- * multiversion_incompatible
- * ]
- */
-
-(function() {
-'use strict';
-
-const collName = "timeseries_field_parsed_as_bson";
-const coll = db.getCollection(collName);
-
-coll.drop();
-const timeField = "badInput']}}}}}}";
-assert.commandWorked(db.createCollection(collName, {timeseries: {timeField: timeField}}));
-
-const timeseriesCollInfo = db.getCollectionInfos({name: "system.buckets." + collName})[0];
-jsTestLog("Timeseries system collection info: " + tojson(timeseriesCollInfo));
-const properties = {};
-properties[timeField] = {
- "bsonType": "date"
-};
-const expectedValidator = {
- "$jsonSchema": {
- "bsonType": "object",
- "required": ["_id", "control", "data"],
- "properties": {
- "_id": {"bsonType": "objectId"},
- "control": {
- "bsonType": "object",
- "required": ["version", "min", "max"],
- "properties": {
- "version": {"bsonType": "number"},
- "min":
- {"bsonType": "object", "required": [timeField], "properties": properties},
- "max":
- {"bsonType": "object", "required": [timeField], "properties": properties},
- "closed": {"bsonType": "bool"},
- "count": {"bsonType": "number", "minimum": 1}
- },
- "additionalProperties": false
- },
- "data": {"bsonType": "object"},
- "meta": {}
- },
- "additionalProperties": false
- }
-};
-
-assert(timeseriesCollInfo.options);
-assert.eq(timeseriesCollInfo.options.validator, expectedValidator);
-
-const doc = {
- a: 1,
- [timeField]: new Date("2021-01-01")
-};
-assert.commandWorked(coll.insert(doc));
-assert.docEq([doc], coll.aggregate([{$match: {}}, {$project: {_id: 0}}]).toArray());
-
-coll.drop();
-assert.commandWorked(db.createCollection(collName, {timeseries: {timeField: "\\"}}));
-coll.drop();
-assert.commandWorked(db.createCollection(collName, {timeseries: {timeField: "\\\\"}}));
-})();
diff --git a/jstests/core/timeseries/timeseries_filter_extended_range.js b/jstests/core/timeseries/timeseries_filter_extended_range.js
deleted file mode 100644
index 2b86e29c943..00000000000
--- a/jstests/core/timeseries/timeseries_filter_extended_range.js
+++ /dev/null
@@ -1,185 +0,0 @@
-/**
- * Test that find/match type queries work properly on dates ouside the 32 bit epoch range,
- * [1970-01-01 00:00:00 UTC - 2038-01-29 03:13:07 UTC].
- *
- * @tags: [
- * # Refusing to run a test that issues an aggregation command with explain because it may
- * # return incomplete results if interrupted by a stepdown.
- * does_not_support_stepdowns,
- * # We need a timeseries collection.
- * requires_timeseries,
- * # Cannot insert into a time-series collection in a multi-document transaction
- * does_not_support_transactions,
- * # Explain of a resolved view must be executed by mongos.
- * directly_against_shardsvrs_incompatible,
- * ]
- */
-
-(function() {
-"use strict";
-const timeFieldName = "time";
-
-/*
- * Creates a collection, populates it, runs the `query` and ensures that the result set
- * is equal to `results`.
- *
- * If overflow is set we create a document with dates above the 32 bit range (year 2040)
- * If underflow is set, we create a document with dates below the 32 bit range (year 1965)
- */
-function runTest(underflow, overflow, query, results) {
- // Setup our DB & our collections.
- const tsColl = db.getCollection(jsTestName());
- tsColl.drop();
-
- assert.commandWorked(
- db.createCollection(tsColl.getName(), {timeseries: {timeField: timeFieldName}}));
-
- const dates = [
- // If underflow, we want to insert a date that would fall below the epoch
- // i.e. 1970-01-01 00:00:00 UTC. Otherwise we use a date within the epoch.
- {[timeFieldName]: underflow ? new Date("1965-01-01") : new Date("1971-01-01")},
- {[timeFieldName]: new Date("1975-01-01")},
- {[timeFieldName]: new Date("1980-01-01")},
- {[timeFieldName]: new Date("1995-01-01")},
- // If overflow, we want to insert a date that would use more than 32 bit milliseconds after
- // the epoch. This overflow will occur 2038-01-29 03:13:07 UTC. Otherwise we go slightly
- // before the end of the 32 bit epoch.
- {[timeFieldName]: overflow ? new Date("2040-01-01") : new Date("2030-01-01")}
- ];
- assert.commandWorked(tsColl.insert(dates));
-
- // Make sure the expected results are in the correct order for comparison below.
- function cmpTimeFields(a, b) {
- return (b[timeFieldName].getTime() - a[timeFieldName].getTime());
- }
- results.sort(cmpTimeFields);
-
- const pipeline = [{$match: query}, {$project: {_id: 0, [timeFieldName]: 1}}];
-
- const plan = tsColl.explain().aggregate(pipeline);
-
- // Verify agg pipeline. We don't want to go through a plan that encourages a sort order to
- // avoid BUS and index selection, so we sort after gathering the results.
- const aggActuals = tsColl.aggregate(pipeline).toArray();
- aggActuals.sort(cmpTimeFields);
- assert.docEq(results, aggActuals, JSON.stringify(plan, null, 4));
-
- // Verify the equivalent find command. We again don't want to go through a plan that
- // encourages a sort order to avoid BUS and index selection, so we sort after gathering the
- // results.
- let findActuals = tsColl.find(query, {_id: 0, [timeFieldName]: 1}).toArray();
- findActuals.sort(cmpTimeFields);
- assert.docEq(findActuals, results);
-}
-
-runTest(false,
- false,
- {[timeFieldName]: {$eq: new Date("1980-01-01")}},
- [{[timeFieldName]: new Date("1980-01-01")}]);
-runTest(false,
- true,
- {[timeFieldName]: {$eq: new Date("2040-01-01")}},
- [{[timeFieldName]: new Date("2040-01-01")}]);
-runTest(true,
- false,
- {[timeFieldName]: {$eq: new Date("1965-01-01")}},
- [{[timeFieldName]: new Date("1965-01-01")}]);
-
-runTest(false,
- false,
- {[timeFieldName]: {$lt: new Date("1980-01-01")}},
- [{[timeFieldName]: new Date("1971-01-01")}, {[timeFieldName]: new Date("1975-01-01")}]);
-runTest(false,
- true,
- {[timeFieldName]: {$lt: new Date("1980-01-01")}},
- [{[timeFieldName]: new Date("1971-01-01")}, {[timeFieldName]: new Date("1975-01-01")}]);
-runTest(true,
- false,
- {[timeFieldName]: {$lt: new Date("1980-01-01")}},
- [{[timeFieldName]: new Date("1965-01-01")}, {[timeFieldName]: new Date("1975-01-01")}]);
-runTest(true,
- true,
- {[timeFieldName]: {$lt: new Date("1980-01-01")}},
- [{[timeFieldName]: new Date("1965-01-01")}, {[timeFieldName]: new Date("1975-01-01")}]);
-
-runTest(false,
- false,
- {[timeFieldName]: {$gt: new Date("1980-01-01")}},
- [{[timeFieldName]: new Date("1995-01-01")}, {[timeFieldName]: new Date("2030-01-01")}]);
-runTest(false,
- true,
- {[timeFieldName]: {$gt: new Date("1980-01-01")}},
- [{[timeFieldName]: new Date("1995-01-01")}, {[timeFieldName]: new Date("2040-01-01")}]);
-runTest(true,
- false,
- {[timeFieldName]: {$gt: new Date("1980-01-01")}},
- [{[timeFieldName]: new Date("1995-01-01")}, {[timeFieldName]: new Date("2030-01-01")}]);
-runTest(true,
- true,
- {[timeFieldName]: {$gt: new Date("1980-01-01")}},
- [{[timeFieldName]: new Date("1995-01-01")}, {[timeFieldName]: new Date("2040-01-01")}]);
-
-runTest(false, false, {[timeFieldName]: {$lte: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1971-01-01")},
- {[timeFieldName]: new Date("1975-01-01")},
- {[timeFieldName]: new Date("1980-01-01")}
-]);
-runTest(false, true, {[timeFieldName]: {$lte: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1971-01-01")},
- {[timeFieldName]: new Date("1975-01-01")},
- {[timeFieldName]: new Date("1980-01-01")}
-]);
-runTest(true, false, {[timeFieldName]: {$lte: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1965-01-01")},
- {[timeFieldName]: new Date("1975-01-01")},
- {[timeFieldName]: new Date("1980-01-01")}
-]);
-runTest(true, true, {[timeFieldName]: {$lte: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1965-01-01")},
- {[timeFieldName]: new Date("1975-01-01")},
- {[timeFieldName]: new Date("1980-01-01")}
-]);
-
-runTest(false, false, {[timeFieldName]: {$gte: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1980-01-01")},
- {[timeFieldName]: new Date("1995-01-01")},
- {[timeFieldName]: new Date("2030-01-01")}
-]);
-runTest(false, true, {[timeFieldName]: {$gte: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1980-01-01")},
- {[timeFieldName]: new Date("1995-01-01")},
- {[timeFieldName]: new Date("2040-01-01")}
-]);
-runTest(true, false, {[timeFieldName]: {$gte: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1980-01-01")},
- {[timeFieldName]: new Date("1995-01-01")},
- {[timeFieldName]: new Date("2030-01-01")}
-]);
-runTest(true, true, {[timeFieldName]: {$gte: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1980-01-01")},
- {[timeFieldName]: new Date("1995-01-01")},
- {[timeFieldName]: new Date("2040-01-01")}
-]);
-
-// Verify ranges that straddle the lower and upper epoch boundaries work properly.
-runTest(
- true, false, {[timeFieldName]: {$gt: new Date("1920-01-01"), $lt: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1965-01-01")},
- {[timeFieldName]: new Date("1975-01-01")},
- ]);
-runTest(
- false, true, {[timeFieldName]: {$gt: new Date("1980-01-01"), $lt: new Date("2050-01-01")}}, [
- {[timeFieldName]: new Date("1995-01-01")},
- {[timeFieldName]: new Date("2040-01-01")},
- ]);
-runTest(
- false, false, {[timeFieldName]: {$gt: new Date("1920-01-01"), $lt: new Date("1980-01-01")}}, [
- {[timeFieldName]: new Date("1971-01-01")},
- {[timeFieldName]: new Date("1975-01-01")},
- ]);
-runTest(
- false, false, {[timeFieldName]: {$gt: new Date("1980-01-01"), $lt: new Date("2050-01-01")}}, [
- {[timeFieldName]: new Date("1995-01-01")},
- {[timeFieldName]: new Date("2030-01-01")},
- ]);
-})();
diff --git a/jstests/core/timeseries/timeseries_geonear_lookup.js b/jstests/core/timeseries/timeseries_geonear_lookup.js
deleted file mode 100644
index 78f68eb014e..00000000000
--- a/jstests/core/timeseries/timeseries_geonear_lookup.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Test that time-series works as expected with $geoNear within a $lookup.
- *
- * @tags: [
- * does_not_support_transactions,
- * requires_pipeline_optimization,
- * # We need a timeseries collection.
- * requires_timeseries,
- * references_foreign_collection,
- * ]
- */
-
-// create a timeseries collection
-const timeFieldName = "time";
-const metaFieldName = "tags";
-const testDB = db;
-
-const tsColl = db.getCollection("ts_coll");
-
-const kMaxDistance = Math.PI * 2.0;
-
-tsColl.drop();
-assert.commandWorked(testDB.createCollection(
- tsColl.getName(), {timeseries: {timeField: timeFieldName, metaField: metaFieldName}}));
-
-assert.commandWorked(tsColl.createIndex({'tags.loc': '2dsphere'}));
-
-tsColl.insert({time: ISODate(), tags: {loc: [40, 40], descr: 0}, value: 0});
-
-const coll2 = db.getCollection("store_min_max_values");
-coll2.drop();
-assert.commandWorked(coll2.insert({_id: 0, minimumDist: 0.0, maximumDist: kMaxDistance}));
-
-coll2.aggregate([{$lookup: {from: tsColl.getName(),
-let: {minVal: "$minimumDist",maxVal:"$maximumDist"},
-pipeline: [
- {$geoNear: {near: {type: "Point", coordinates: [0, 0]},
- key: 'tags.loc',
- distanceField: "tags.distance"}}],
- as: 'output'}}]);
diff --git a/jstests/core/timeseries/timeseries_geonear_measurements.js b/jstests/core/timeseries/timeseries_geonear_measurements.js
index abbf7db9596..5c5427a02d1 100644
--- a/jstests/core/timeseries/timeseries_geonear_measurements.js
+++ b/jstests/core/timeseries/timeseries_geonear_measurements.js
@@ -23,10 +23,10 @@
(function() {
"use strict";
+load("jstests/core/timeseries/libs/timeseries.js");
load("jstests/libs/analyze_plan.js");
-load("jstests/libs/feature_flag_util.js");
-if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
jsTestLog(
"Skipped test as the featureFlagTimeseriesMetricIndexes feature flag is not enabled.");
return;
diff --git a/jstests/core/timeseries/timeseries_graph_lookup.js b/jstests/core/timeseries/timeseries_graph_lookup.js
index 25f47aa2cef..7b152cc6b1f 100644
--- a/jstests/core/timeseries/timeseries_graph_lookup.js
+++ b/jstests/core/timeseries/timeseries_graph_lookup.js
@@ -5,7 +5,6 @@
* does_not_support_transactions,
* requires_timeseries,
* requires_fcv_51,
- * references_foreign_collection,
* ]
*/
(function() {
diff --git a/jstests/core/timeseries/timeseries_groupby_reorder.js b/jstests/core/timeseries/timeseries_groupby_reorder.js
deleted file mode 100644
index 774d867d3f6..00000000000
--- a/jstests/core/timeseries/timeseries_groupby_reorder.js
+++ /dev/null
@@ -1,233 +0,0 @@
-/**
- * Test the behavior of $group on time-series collections. Specifically, we are targeting rewrites
- * that replace bucket unpacking with $group over the buckets collection. Currently, only $min/$max
- * are supported for the rewrites.
- *
- * @tags: [
- * directly_against_shardsvrs_incompatible,
- * does_not_support_stepdowns,
- * does_not_support_transactions,
- * requires_fcv_60,
- * ]
- */
-(function() {
-"use strict";
-
-load("jstests/libs/fixture_helpers.js");
-load("jstests/core/timeseries/libs/timeseries.js");
-
-const coll = db.timeseries_groupby_reorder;
-coll.drop();
-
-// We will only check correctness of the results here as checking the plan in JSTests is brittle and
-// is better done in document_source_internal_unpack_bucket_test/group_reorder_test.cpp. For the
-// cases when the re-write isn't applicable, the used datasets should yield wrong result if the
-// re-write is applied.
-function runGroupRewriteTest(docs, pipeline, expectedResults) {
- coll.drop();
- db.createCollection(coll.getName(), {timeseries: {metaField: "meta", timeField: "time"}});
- coll.insertMany(docs);
- assert.docEq(expectedResults, coll.aggregate(pipeline).toArray(), () => {
- return `Pipeline: ${tojson(pipeline)}. Explain: ${
- tojson(coll.explain().aggregate(pipeline))}`;
- });
-}
-
-// Test with measurement group key -- a rewrite in this situation would be wrong.
-(function testNonMetaGroupKey() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, key: 2, val: 1}, // global min
- {time: t, meta: 1, key: 1, val: 3}, // min for key = 1
- {time: t, meta: 1, key: 1, val: 5}, // max for key = 1
- {time: t, meta: 1, key: 2, val: 7}, // global max
- ];
- runGroupRewriteTest(docs,
- [{$group: {_id: "$key", min: {$min: "$val"}}}, {$match: {_id: 1}}],
- [{"_id": 1, "min": 3}]);
- runGroupRewriteTest(docs,
- [{$group: {_id: "$key", max: {$max: "$val"}}}, {$match: {_id: 1}}],
- [{"_id": 1, "max": 5}]);
-})();
-
-// While a group with const group key can be re-written in terms of a group on the buckets, we don't
-// currently do it. However, when/if we start doing it, it should work.
-(function testConstGroupKey_NoFilter() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, val: 0},
- {time: t, meta: 1, val: 1},
- {time: t, meta: 1, val: 5},
- ];
- runGroupRewriteTest(
- docs, [{$group: {_id: null, min: {$min: "$val"}}}], [{"_id": null, "min": 0}]);
- runGroupRewriteTest(
- docs, [{$group: {_id: null, max: {$max: "$val"}}}], [{"_id": null, "max": 5}]);
-})();
-
-// With a filter on meta the group re-write would still apply if the group key is const.
-(function testConstGroupKey_WithFilterOnMeta() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, val: 0},
- {time: t, meta: 2, val: 1},
- {time: t, meta: 2, val: 3},
- {time: t, meta: 1, val: 5},
- ];
- runGroupRewriteTest(docs,
- [{$match: {meta: 2}}, {$group: {_id: null, min: {$min: "$val"}}}],
- [{"_id": null, "min": 1}]);
- runGroupRewriteTest(docs,
- [{$match: {meta: 2}}, {$group: {_id: null, max: {$max: "$val"}}}],
- [{"_id": null, "max": 3}]);
-})();
-
-// In presense of a non-meta filter the group re-write doesn't apply even if the group key is const.
-(function testConstGroupKey_WithFilterOnMeasurement() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, val: 0, include: false},
- {time: t, meta: 1, val: 1, include: true},
- {time: t, meta: 1, val: 5, include: false},
- ];
- runGroupRewriteTest(docs,
- [{$match: {include: true}}, {$group: {_id: null, min: {$min: "$val"}}}],
- [{"_id": null, "min": 1}]);
- runGroupRewriteTest(docs,
- [{$match: {include: true}}, {$group: {_id: null, max: {$max: "$val"}}}],
- [{"_id": null, "max": 1}]);
-})();
-
-// Test with meta group key. The group re-write applies.
-(function testMetaGroupKey_NoFilter() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, val: 5},
- {time: t, meta: 2, val: 4},
- {time: t, meta: 2, val: 3},
- {time: t, meta: 1, val: 1},
- ];
- runGroupRewriteTest(docs,
- [{$group: {_id: "$meta", min: {$min: "$val"}}}, {$match: {_id: 2}}],
- [{"_id": 2, "min": 3}]);
- runGroupRewriteTest(docs,
- [{$group: {_id: "$meta", max: {$max: "$val"}}}, {$match: {_id: 2}}],
- [{"_id": 2, "max": 4}]);
-})();
-
-// Test with meta group key preceeded by a filter on the meta key. The re-write still applies.
-(function testMetaGroupKey_WithFilterOnMeta() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, val: 5},
- {time: t, meta: 2, val: 4},
- {time: t, meta: 2, val: 3},
- {time: t, meta: 1, val: 1},
- ];
- runGroupRewriteTest(docs,
- [{$match: {meta: 2}}, {$group: {_id: "$meta", min: {$min: "$val"}}}],
- [{"_id": 2, "min": 3}]);
- runGroupRewriteTest(docs,
- [{$match: {meta: 2}}, {$group: {_id: "$meta", max: {$max: "$val"}}}],
- [{"_id": 2, "max": 4}]);
-})();
-
-// Test with meta group key preceeded by a filter on a measurement key. The re-write doesn't apply.
-(function testMetaGroupKey_WithFilterOnMeasurement() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, val: 3, include: false},
- {time: t, meta: 1, val: 4, include: true},
- {time: t, meta: 1, val: 5, include: false},
- ];
- runGroupRewriteTest(docs,
- [{$match: {include: true}}, {$group: {_id: "$meta", min: {$min: "$val"}}}],
- [{"_id": 1, "min": 4}]);
- runGroupRewriteTest(docs,
- [{$match: {include: true}}, {$group: {_id: "$meta", max: {$max: "$val"}}}],
- [{"_id": 1, "max": 4}]);
-})();
-
-// Test SERVER-73822 fix: complex $min and $max (i.e. not just straight field refs) work correctly.
-(function testMetaGroupKey_WithNonPathExpressionUnderMinMax() {
- const t = new Date();
- // min(a+b) != min(a) + min(b) and max(a+b) != max(a) + max(b)
- const docs = [
- {time: t, meta: 1, a: 1, b: 20}, // max(a + b)
- {time: t, meta: 1, a: 2, b: 10},
- {time: t, meta: 1, a: 3, b: 1}, // min(a + b)
- ];
- runGroupRewriteTest(docs,
- [{$group: {_id: "$meta", min: {$min: {$add: ["$a", "$b"]}}}}],
- [{"_id": 1, "min": 4}]);
- runGroupRewriteTest(docs,
- [{$group: {_id: "$meta", max: {$max: {$add: ["$a", "$b"]}}}}],
- [{"_id": 1, "max": 21}]);
-})();
-
-// Test with meta group key and a non-min/max accumulator that doesn't use any fields. The buckets
-// still have to be unpacked because we don't know the number of events in uncompressed buckets.
-(function testMetaGroupKey_WithAccumulatorNotUsingAnyFields() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, val: 3},
- {time: t, meta: 3, val: 4},
- {time: t, meta: 1, val: 5},
- ];
- runGroupRewriteTest(
- docs, [{$group: {_id: "$meta", x: {$sum: 1}}}, {$match: {_id: 1}}], [{"_id": 1, "x": 2}]);
-})();
-
-// Test with meta group key and a non-min/max accumulator that uses only the meta field. This query
-// is _not_ eligible for the re-write w/o bucket unpacking because while it doesn't depend on any
-// fields of the individual events it still depends on the number of events in a bucket.
-(function testMetaGroupKey_WithNonMinMaxAccumulatorOnMeta() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, val: 3},
- {time: t, meta: 3, val: 4},
- {time: t, meta: 1, val: 5},
- ];
- runGroupRewriteTest(docs,
- [{$group: {_id: "$meta", x: {$sum: "$meta"}}}, {$match: {_id: 1}}],
- [{"_id": 1, "x": 2}]);
-})();
-
-// In presence of a filter $min and $max on the meta field cannot be re-written because a filter
-// might end up selecting nothing in buckets with a particular meta.
-(function testMetaGroupKey_WithAccumulatorOnMeta_WithFilterOnMeasurement() {
- const t = new Date();
- const docs = [
- {time: t, meta: 1, include: false},
- ];
- runGroupRewriteTest(
- docs, [{$match: {include: true}}, {$group: {_id: "$meta", x: {$min: "$meta"}}}], []);
-})();
-
-// Test min/max on the time field (cannot rewrite $min because the control.time.min is rounded
-// down).
-(function testMetaGroupKey_WithMinMaxOnTime() {
- const docs = [
- {time: ISODate("2023-07-20T23:16:47.683Z"), meta: 1},
- ];
- runGroupRewriteTest(docs,
- [{$group: {_id: "$meta", min: {$min: "$time"}}}],
- [{_id: 1, min: ISODate("2023-07-20T23:16:47.683Z")}]);
-})();
-
-// Test a group key which is an object with single field path. Ensure that the output perseveres the
-// user requested object structure for _id field.
-(function testMetaGroupKey_ObjectWithSingleFieldPathElement() {
- const t = new Date();
- const docs = [
- {time: t, meta: {a: 1}, val: 5},
- {time: t, meta: {a: 2}, val: 4},
- {time: t, meta: {a: 2}, val: 3},
- {time: t, meta: {a: 1}, val: 1},
- ];
- runGroupRewriteTest(
- docs,
- [{$group: {_id: {d: "$meta.a"}, min: {$min: "$val"}}}, {$match: {_id: {d: 2}}}],
- [{"_id": {d: 2}, "min": 3}]);
-})();
-})();
diff --git a/jstests/core/timeseries/timeseries_index.js b/jstests/core/timeseries/timeseries_index.js
index 9547362d105..bef86453999 100644
--- a/jstests/core/timeseries/timeseries_index.js
+++ b/jstests/core/timeseries/timeseries_index.js
@@ -11,9 +11,8 @@
(function() {
"use strict";
-load("jstests/core/timeseries/libs/timeseries.js");
-load("jstests/libs/feature_flag_util.js");
load("jstests/libs/fixture_helpers.js");
+load("jstests/core/timeseries/libs/timeseries.js");
TimeseriesTest.run((insert) => {
const collNamePrefix = 'timeseries_index_';
@@ -226,7 +225,7 @@ TimeseriesTest.run((insert) => {
runTest({[metaFieldName + '.location']: "2d", [metaFieldName + '.tag1']: -1},
{'meta.location': "2d", 'meta.tag1': -1});
- if (FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+ if (TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
// Measurement 2dsphere index
runTest({'loc': '2dsphere'}, {'data.loc': '2dsphere_bucket'});
}
@@ -243,7 +242,7 @@ TimeseriesTest.run((insert) => {
coll.getName(), {timeseries: {timeField: timeFieldName, metaField: metaFieldName}}));
assert.commandWorked(insert(coll, doc), 'failed to insert doc: ' + tojson(doc));
- if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+ if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
// Reject index keys that do not include the metadata field.
assert.commandFailedWithCode(coll.createIndex({not_metadata: 1}),
ErrorCodes.CannotCreateIndex);
@@ -266,7 +265,7 @@ TimeseriesTest.run((insert) => {
[ErrorCodes.CannotCreateIndex, ErrorCodes.InvalidOptions]);
};
- if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+ if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
// Partial indexes are not supported on time-series collections if the time-series metric
// feature flag is disabled.
testCreateIndexFailed({[metaFieldName]: 1}, {partialFilterExpression: {meta: {$gt: 5}}});
diff --git a/jstests/core/timeseries/timeseries_index_partial.js b/jstests/core/timeseries/timeseries_index_partial.js
index 014158c3542..eb2512b1bd7 100644
--- a/jstests/core/timeseries/timeseries_index_partial.js
+++ b/jstests/core/timeseries/timeseries_index_partial.js
@@ -2,8 +2,6 @@
* Test creating and using partial indexes, on a time-series collection.
*
* @tags: [
- * # TODO (SERVER-73316): remove
- * assumes_against_mongod_not_mongos,
* does_not_support_stepdowns,
* does_not_support_transactions,
* requires_fcv_52,
@@ -14,10 +12,10 @@
(function() {
"use strict";
+load("jstests/core/timeseries/libs/timeseries.js");
load("jstests/libs/analyze_plan.js");
-load("jstests/libs/feature_flag_util.js");
-if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
jsTestLog(
"Skipped test as the featureFlagTimeseriesMetricIndexes feature flag is not enabled.");
return;
@@ -80,24 +78,10 @@ assert.commandFailedWithCode(coll.createIndex({a: 1}, {partialFilterExpression:
// Test creating and using a partial index.
{
- let ixscanInWinningPlan = 0;
-
- // Make sure the {a: 1} index was considered for this query.
+ // Make sure the query uses the {a: 1} index.
function checkPlan(predicate) {
const explain = coll.find(predicate).explain();
- let scan = getAggPlanStage(explain, 'IXSCAN');
- // If scan is not present, check rejected plans
- if (scan === null) {
- const rejectedPlans = getRejectedPlans(getAggPlanStage(explain, "$cursor")["$cursor"]);
- if (rejectedPlans.length === 1) {
- const scans = getPlanStages(getRejectedPlan(rejectedPlans[0]), "IXSCAN");
- if (scans.length === 1) {
- scan = scans[0];
- }
- }
- } else {
- ixscanInWinningPlan++;
- }
+ const scan = getAggPlanStage(explain, 'IXSCAN');
const indexes = buckets.getIndexes();
assert(scan,
"Expected an index scan for predicate: " + tojson(predicate) +
@@ -106,10 +90,10 @@ assert.commandFailedWithCode(coll.createIndex({a: 1}, {partialFilterExpression:
}
// Make sure the query results match a collection-scan plan.
function checkResults(predicate) {
- const result = coll.aggregate([{$match: predicate}], {hint: {a: 1}}).toArray();
+ const result = coll.aggregate({$match: predicate}).toArray();
const unindexed =
coll.aggregate([{$_internalInhibitOptimization: {}}, {$match: predicate}]).toArray();
- assert.sameMembers(result, unindexed);
+ assert.docEq(result, unindexed);
}
function checkPlanAndResults(predicate) {
checkPlan(predicate);
@@ -149,6 +133,10 @@ assert.commandFailedWithCode(coll.createIndex({a: 1}, {partialFilterExpression:
const t1 = ISODate('2000-01-01T00:00:01Z');
const t2 = ISODate('2000-01-01T00:00:02Z');
+ // When the collection is sharded, there is an index on time that can win, instead of the
+ // partial index. So only check the results in that case, not the plan.
+ const check = FixtureHelpers.isSharded(buckets) ? checkResults : checkPlanAndResults;
+
assert.commandWorked(coll.dropIndex({a: 1}));
assert.commandWorked(
coll.createIndex({a: 1}, {partialFilterExpression: {[timeField]: {$lt: t1}}}));
@@ -177,7 +165,6 @@ assert.commandFailedWithCode(coll.createIndex({a: 1}, {partialFilterExpression:
assert.commandWorked(coll.dropIndex({a: 1}));
assert.sameMembers(coll.getIndexes(), extraIndexes);
assert.sameMembers(buckets.getIndexes(), extraBucketIndexes);
- assert.gt(ixscanInWinningPlan, 0);
}
// Check that partialFilterExpression can use a mixture of metadata, time, and measurement fields,
diff --git a/jstests/core/timeseries/timeseries_index_spec.js b/jstests/core/timeseries/timeseries_index_spec.js
index d3822dc642b..f13c64dd80b 100644
--- a/jstests/core/timeseries/timeseries_index_spec.js
+++ b/jstests/core/timeseries/timeseries_index_spec.js
@@ -16,7 +16,6 @@
"use strict";
load("jstests/core/timeseries/libs/timeseries.js");
-load("jstests/libs/feature_flag_util.js");
TimeseriesTest.run(() => {
const collName = "timeseries_index_spec";
@@ -86,7 +85,7 @@ TimeseriesTest.run(() => {
{name: "time_meta_field_downgradable"}));
verifyAndDropIndex(/*isDowngradeCompatible=*/true, "time_meta_field_downgradable");
- if (FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+ if (TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
assert.commandWorked(coll.createIndex({x: 1}, {name: "x_1"}));
verifyAndDropIndex(/*isDowngradeCompatible=*/false, "x_1");
@@ -111,7 +110,7 @@ TimeseriesTest.run(() => {
// Creating an index directly on the buckets collection is permitted. However, these types of
// index creations will not have an "originalSpec" field and rely on the reverse mapping
// mechanism.
- if (FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+ if (TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
assert.commandWorked(
bucketsColl.createIndex({"control.min.y": 1, "control.max.y": 1}, {name: "y"}));
diff --git a/jstests/core/timeseries/timeseries_index_use.js b/jstests/core/timeseries/timeseries_index_use.js
index 6ce128ecbbd..8770047f4d2 100644
--- a/jstests/core/timeseries/timeseries_index_use.js
+++ b/jstests/core/timeseries/timeseries_index_use.js
@@ -50,9 +50,8 @@ const generateTest = (useHint) => {
/**
* Creates the index specified by the spec and options, then explains the query to ensure
- * that the created index is used or was considered by multi-planner.
- * Runs the query and verifies that the expected number of documents are matched.
- * Finally, deletes the created index.
+ * that the created index is used. Runs the query and verifies that the expected number of
+ * documents are matched. Finally, deletes the created index.
*/
const testQueryUsesIndex = function(
filter, numMatches, indexSpec, indexOpts = {}, queryOpts = {}) {
@@ -68,23 +67,9 @@ const generateTest = (useHint) => {
assert.eq(numMatches, query.itcount());
const explain = query.explain();
- if (useHint) {
- const ixscan = getAggPlanStage(explain, "IXSCAN");
- assert.neq(null, ixscan, tojson(explain));
- assert.eq("testIndexName", ixscan.indexName, tojson(ixscan));
- } else {
- let ixscan = getAggPlanStage(explain, "IXSCAN");
- // If ixscan is not present, check rejected plans
- if (ixscan === null) {
- const rejectedPlans =
- getRejectedPlans(getAggPlanStage(explain, "$cursor")["$cursor"]);
- assert.eq(1, rejectedPlans.length);
- const ixscans = getPlanStages(getRejectedPlan(rejectedPlans[0]), "IXSCAN");
- assert.eq(1, ixscans.length);
- ixscan = ixscans[0];
- }
- assert.eq("testIndexName", ixscan.indexName, tojson(ixscan));
- }
+ const ixscan = getAggPlanStage(explain, "IXSCAN");
+ assert.neq(null, ixscan, tojson(explain));
+ assert.eq("testIndexName", ixscan.indexName, tojson(ixscan));
assert.commandWorked(coll.dropIndex("testIndexName"));
};
diff --git a/jstests/core/timeseries/timeseries_insert_mixed_schema_bucket.js b/jstests/core/timeseries/timeseries_insert_mixed_schema_bucket.js
deleted file mode 100644
index cbce31e9795..00000000000
--- a/jstests/core/timeseries/timeseries_insert_mixed_schema_bucket.js
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Tests directly inserting a time-series bucket with mixed schema.
- *
- * @tags: [
- * # $listCatalog does not include the tenant prefix in its results.
- * command_not_supported_in_serverless,
- * requires_timeseries,
- * # $listCatalog not supported inside of a multi-document transaction
- * does_not_support_transactions,
- * # $listCatalog only exists since v6
- * multiversion_incompatible,
- * ]
- */
-(function() {
-"use strict";
-
-load("jstests/core/timeseries/libs/timeseries.js"); // For 'TimeseriesTest'.
-
-TestData.skipEnforceTimeseriesBucketsAreAlwaysCompressedOnValidate = true;
-
-const testDB = db.getSiblingDB(jsTestName());
-const collName = "ts";
-
-assert.commandWorkedOrFailedWithCode(testDB.runCommand({drop: collName}),
- ErrorCodes.NamespaceNotFound);
-assert.commandWorked(
- testDB.createCollection(collName, {timeseries: {timeField: "t", metaField: "m"}}));
-const coll = testDB[collName];
-const bucketsColl = testDB["system.buckets." + collName];
-
-const bucket = {
- _id: ObjectId("65a6eb806ffc9fa4280ecac4"),
- control: {
- version: NumberInt(1),
- min: {
- _id: ObjectId("65a6eba7e6d2e848e08c3750"),
- t: ISODate("2024-01-16T20:48:00Z"),
- a: 1,
- },
- max: {
- _id: ObjectId("65a6eba7e6d2e848e08c3751"),
- t: ISODate("2024-01-16T20:48:39.448Z"),
- a: "a",
- },
- },
- meta: 0,
- data: {
- _id: {
- 0: ObjectId("65a6eba7e6d2e848e08c3750"),
- 1: ObjectId("65a6eba7e6d2e848e08c3751"),
- },
- t: {
- 0: ISODate("2024-01-16T20:48:39.448Z"),
- 1: ISODate("2024-01-16T20:48:39.448Z"),
- },
- a: {
- 0: "a",
- 1: 1,
- },
- }
-};
-
-assert.commandFailedWithCode(bucketsColl.insert(bucket),
- ErrorCodes.CannotInsertTimeseriesBucketsWithMixedSchema);
-assert.eq(TimeseriesTest.bucketsMayHaveMixedSchemaData(bucketsColl), false);
-assert.commandWorked(
- testDB.runCommand({collMod: collName, timeseriesBucketsMayHaveMixedSchemaData: true}));
-assert.eq(TimeseriesTest.bucketsMayHaveMixedSchemaData(bucketsColl), true);
-assert.commandWorked(bucketsColl.insert(bucket));
-assert.commandWorked(bucketsColl.deleteOne({_id: bucket._id}));
-assert.eq(TimeseriesTest.bucketsMayHaveMixedSchemaData(bucketsColl), true);
-assert.commandWorked(
- testDB.runCommand({collMod: collName, timeseriesBucketsMayHaveMixedSchemaData: false}));
-assert.eq(TimeseriesTest.bucketsMayHaveMixedSchemaData(bucketsColl), false);
-})();
diff --git a/jstests/core/timeseries/timeseries_internal_bucket_geo_within.js b/jstests/core/timeseries/timeseries_internal_bucket_geo_within.js
index 2e350ebdbb0..9c237d8dd77 100644
--- a/jstests/core/timeseries/timeseries_internal_bucket_geo_within.js
+++ b/jstests/core/timeseries/timeseries_internal_bucket_geo_within.js
@@ -4,7 +4,7 @@
* collection.
*
* @tags: [
- * requires_fcv_60,
+ * requires_fcv_51,
* requires_pipeline_optimization,
* requires_timeseries,
* does_not_support_stepdowns,
@@ -47,6 +47,10 @@ for (let collScanStage of collScanStages) {
"field": "loc"
}
};
+ // TODO SERVER-60373 Fix duplicate predicates for sharded time-series collection
+ if (FixtureHelpers.isSharded(bucketsColl)) {
+ expectedPredicate = {$and: [expectedPredicate, expectedPredicate]};
+ }
assert.docEq(expectedPredicate, collScanStage.filter, collScanStages);
}
diff --git a/jstests/core/timeseries/timeseries_lastpoint_top.js b/jstests/core/timeseries/timeseries_lastpoint_top.js
index c85f48fb076..2efd352b574 100644
--- a/jstests/core/timeseries/timeseries_lastpoint_top.js
+++ b/jstests/core/timeseries/timeseries_lastpoint_top.js
@@ -27,7 +27,6 @@ assert.commandWorked(testDB.dropDatabase());
// Do not run the rest of the tests if the lastpoint optimization is disabled.
if (!FeatureFlagUtil.isEnabled(db, "LastPointQuery")) {
- jsTestLog("Skipping the test.");
return;
}
diff --git a/jstests/core/timeseries/timeseries_lookup.js b/jstests/core/timeseries/timeseries_lookup.js
index 6d559e9356d..c173764a591 100644
--- a/jstests/core/timeseries/timeseries_lookup.js
+++ b/jstests/core/timeseries/timeseries_lookup.js
@@ -5,13 +5,11 @@
* does_not_support_transactions,
* requires_timeseries,
* requires_fcv_51,
- * references_foreign_collection,
* ]
*/
(function() {
"use strict";
-load("jstests/aggregation/extras/utils.js");
load("jstests/core/timeseries/libs/timeseries.js");
TimeseriesTest.run((insert) => {
@@ -26,44 +24,43 @@ TimeseriesTest.run((insert) => {
Random.setRandomSeed();
const hosts = TimeseriesTest.generateHosts(numHosts);
- let
- testFunc = function(collAOption, collBOption) {
- // Prepare two time-series collections.
- const collA = testDB.getCollection("a");
- const collB = testDB.getCollection("b");
- collA.drop();
- collB.drop();
- assert.commandWorked(testDB.createCollection(collA.getName(), collAOption));
- assert.commandWorked(testDB.createCollection(collB.getName(), collBOption));
-
- let entryCountPerHost = new Array(numHosts).fill(0);
-
- // Insert into collA, one entry per host.
- for (let i = 0; i < numHosts; i++) {
- let host = hosts[i];
- assert.commandWorked(insert(collA, {
- measurement: "cpu",
- time: ISODate(),
- tags: host.tags,
- }));
- }
-
- // Insert some random documents to collB.
- for (let i = 0; i < numDocs; i++) {
- let host = TimeseriesTest.getRandomElem(hosts);
- assert.commandWorked(insert(collB, {
- measurement: "cpu",
- time: ISODate(),
- tags: host.tags,
- }));
- // Here we extract the hostId from "host.tags.hostname". It is expected that the
- // "host.tags.hostname" is in the form of 'host_<hostNum>'.
- entryCountPerHost[parseInt(
- host.tags.hostname.substring(5, host.tags.hostname.length))]++;
- }
-
- // Equality Match
- let results = collA.aggregate([
+ let testFunc = function(collAOption, collBOption) {
+ // Prepare two time-series collections.
+ const collA = testDB.getCollection("a");
+ const collB = testDB.getCollection("b");
+ collA.drop();
+ collB.drop();
+ assert.commandWorked(testDB.createCollection(collA.getName(), collAOption));
+ assert.commandWorked(testDB.createCollection(collB.getName(), collBOption));
+
+ let entryCountPerHost = new Array(numHosts).fill(0);
+
+ // Insert into collA, one entry per host.
+ for (let i = 0; i < numHosts; i++) {
+ let host = hosts[i];
+ assert.commandWorked(insert(collA, {
+ measurement: "cpu",
+ time: ISODate(),
+ tags: host.tags,
+ }));
+ }
+
+ // Insert some random documents to collB.
+ for (let i = 0; i < numDocs; i++) {
+ let host = TimeseriesTest.getRandomElem(hosts);
+ assert.commandWorked(insert(collB, {
+ measurement: "cpu",
+ time: ISODate(),
+ tags: host.tags,
+ }));
+ // Here we extract the hostId from "host.tags.hostname". It is expected that the
+ // "host.tags.hostname" is in the form of 'host_<hostNum>'.
+ entryCountPerHost[parseInt(
+ host.tags.hostname.substring(5, host.tags.hostname.length))]++;
+ }
+
+ // Equality Match
+ let results = collA.aggregate([
{
$lookup: {
from: collB.getName(),
@@ -82,106 +79,13 @@ TimeseriesTest.run((insert) => {
},
{$sort: {host: 1}}
]).toArray();
- assert.eq(numHosts, results.length, results);
- for (let i = 0; i < numHosts; i++) {
- assert.eq({host: "host_" + i, matchedB: entryCountPerHost[i]}, results[i], results);
- }
+ assert.eq(numHosts, results.length, results);
+ for (let i = 0; i < numHosts; i++) {
+ assert.eq({host: "host_" + i, matchedB: entryCountPerHost[i]}, results[i], results);
+ }
- // Equality Match With Let (uncorrelated)
- // Make sure injected $sequentialDocumentCache (right after unpack bucket stage)
- // in the inner pipeline is removed.
- results = collA.aggregate([
- {
- $lookup: {
- from: collB.getName(),
- let: {"outer_hostname": "$tags.hostname"},
- pipeline: [
- // $match will be pushed before unpack bucket stage
- {$match: {$expr: {$eq: ["$$outer_hostname", hosts[0].tags.hostname]}}},
- ],
- as: "matchedB"
- }
- }, {
- $project: {
- _id: 0,
- host: "$tags.hostname",
- matchedB: {
- $size: "$matchedB"
- }
- }
- },
- {$sort: {host: 1}}
- ]).toArray();
- assert.eq(numHosts, results.length, results);
- for (let i = 0; i < numHosts; i++) {
- const matched = i === 0 ? numDocs : 0;
- assert.eq({host: "host_" + i, matchedB: matched}, results[i], results);
- }
-
- // Equality Match With Let (uncorrelated)
- // Make sure injected $sequentialDocumentCache in the inner pipeline is removed.
- // $sequentialDocumentCache is not located right after unpack bucket stage.
- results = collA.aggregate([
- {
- $lookup: {
- from: collB.getName(),
- let: {"outer_hostname": "$tags.hostname"},
- pipeline: [
- {$match: {$expr: {$eq: ["$$outer_hostname", hosts[0].tags.hostname]}}},
- {$set: {foo: {$const: 123}}}, // uncorrelated
- ],
- as: "matchedB"
- }
- }, {
- $project: {
- _id: 0,
- host: "$tags.hostname",
- matchedB: {
- $size: "$matchedB"
- }
- }
- },
- {$sort: {host: 1}}
- ]).toArray();
- assert.eq(numHosts, results.length, results);
- for (let i = 0; i < numHosts; i++) {
- const matched = i === 0 ? numDocs : 0;
- assert.eq({host: "host_" + i, matchedB: matched}, results[i], results);
- }
-
- // Equality Match With Let (correlated, no $match re-order)
- // Make sure injected $sequentialDocumentCache in the inner pipeline is removed.
- // $sequentialDocumentCache is located at the very end of pipeline.
- results = collA.aggregate([
- {
- $lookup: {
- from: collB.getName(),
- let: {"outer_hostname": "$tags.hostname"},
- pipeline: [
- {$match: {$expr: {$eq: ["$$outer_hostname", hosts[0].tags.hostname]}}},
- {$set: {foo: "$$outer_hostname"}}, // correlated
- ],
- as: "matchedB"
- }
- }, {
- $project: {
- _id: 0,
- host: "$tags.hostname",
- matchedB: {
- $size: "$matchedB"
- }
- }
- },
- {$sort: {host: 1}}
- ]).toArray();
- assert.eq(numHosts, results.length, results);
- for (let i = 0; i < numHosts; i++) {
- const matched = i === 0 ? numDocs : 0;
- assert.eq({host: "host_" + i, matchedB: matched}, results[i], results);
- }
-
- // Unequal joins
- results = collA.aggregate([
+ // Unequal joins
+ results = collA.aggregate([
{
$lookup: {
from: collB.getName(),
@@ -210,28 +114,13 @@ TimeseriesTest.run((insert) => {
},
{$sort: {host: 1}}
]).toArray();
- assert.eq(numHosts, results.length, results);
- let expectedCount = 0;
- for (let i = 0; i < numHosts; i++) {
- expectedCount += entryCountPerHost[i];
- assert.eq(
- {host: "host_" + i, matchedB: expectedCount}, results[i], entryCountPerHost);
- }
-
- // $sequenceDocumentsCache might optimize out $internalUnpackBucket and cause a
- // crash on such query.
- results = collA.aggregate([
- {$lookup: {
- from: collB.getName(),
- as: 'docs',
- let: {},
- pipeline: [
- {$sort: {_id: 1}}
- ]
- }}
- ]).toArray();
- assert.eq(numHosts, results.length, results);
- };
+ assert.eq(numHosts, results.length, results);
+ let expectedCount = 0;
+ for (let i = 0; i < numHosts; i++) {
+ expectedCount += entryCountPerHost[i];
+ assert.eq({host: "host_" + i, matchedB: expectedCount}, results[i], entryCountPerHost);
+ }
+ };
// Exhaust the combinations of non-time-series and time-series collections for inner and outer
// $lookup collections.
@@ -247,91 +136,3 @@ TimeseriesTest.run((insert) => {
});
});
})();
-
-{
- // Test that we get the right results for $lookup on a timeseries collection with an internal
- // pipeline containing both correlated and uncorrelated $match stages. Ensures we do not cache
- // the results of this internal pipeline incorrectly
- // (src/mongo/db/pipeline/document_source_sequential_document_cache.h) regardless of the order
- // of the $match stages.
- const testDB = db.getSiblingDB(jsTestName());
- testDB.local.insertMany([{_id: 0, key: 1}, {_id: 1, key: 2}]);
- testDB.createCollection("foreign", {timeseries: {timeField: "time", metaField: "meta"}});
- testDB.foreign.insertMany([
- {time: new Date(), _id: 0, meta: 1, val1: 42, val2: 100},
- {time: new Date(), _id: 2, meta: 2, val1: 17, val2: 100}
- ]);
-
- // The $sequentialCache (document_source_sequential_document_cache.h) decides whether or not it
- // can cache the results of the internal lookup pipeline based on if the pipeline is correlated
- // or uncorrelated. With timeseries, many rewrites occur which can merge $match stages together,
- // have them pushed into the $_internalUnpackBucket stage as an eventFilter, or push them in
- // front of the
- // $_internalUnpackBucket stage. We need to make sure that the ability of the cache to recognize
- // when there is a correlated $match in the pipeline to remain regardless of these rewrites.
- (function testUncorrelatedFollowedByCorrelatedMatch() {
- const lookupStage = {$lookup: {
- from: "foreign",
- let: {lkey: "$key"},
- pipeline: [
- {$match: {$expr: {$lt: ["$val1","$val2"]}}},
- {$match: {$expr: {$eq: ["$meta","$$lkey"]}}},
- {$project: {lkey: "$$lkey",fkey: "$meta",val: "$val1",_id: 0,}},
- ],
- as: "joined"
- }};
- const result = testDB.local.aggregate(lookupStage);
- assertArrayEq({
- actual: result.toArray(),
- expected: [
- {"_id": 1, "key": 2, "joined": [{"lkey": 2, "fkey": 2, "val": 17}]},
- {"_id": 0, "key": 1, "joined": [{"lkey": 1, "fkey": 1, "val": 42}]}
- ],
- extraErrorMsg: `Unexpected result of running pipeline ${tojson(lookupStage)}`
- });
- })();
-
- (function testCorrelatedFollowedByUncorrelatedMatch() {
- const lookupStage = {$lookup: {
- from: "foreign",
- let: {lkey: "$key"},
- pipeline: [
- {$match: {$expr: {$eq: ["$meta","$$lkey"]}}},
- {$match: {$expr: {$lt: ["$val1","$val2"]}}},
- {$project: {lkey: "$$lkey",fkey: "$meta",val: "$val1",_id: 0,}},
- ],
- as: "joined"
- }};
- const result = testDB.local.aggregate(lookupStage);
- assertArrayEq({
- actual: result.toArray(),
- expected: [
- {"_id": 1, "key": 2, "joined": [{"lkey": 2, "fkey": 2, "val": 17}]},
- {"_id": 0, "key": 1, "joined": [{"lkey": 1, "fkey": 1, "val": 42}]}
- ],
- extraErrorMsg: `Unexpected result of running pipeline ${tojson(lookupStage)}`
- });
- })();
-
- (function testUncorrelatedFollowedByUncorrelatedMatch() {
- const lookupStage = {$lookup: {
- from: "foreign",
- let: {lkey: "$key"},
- pipeline: [
- {$match: {$expr: {$lt: ["$meta","$val1"]}}},
- {$match: {$expr: {$lt: ["$val1","$val2"]}}},
- {$project: {meta: "$meta",val: "$val1",_id: 0,}},
- ],
- as: "joined"
- }};
- const result = testDB.local.aggregate(lookupStage);
- assertArrayEq({
- actual: result.toArray(),
- expected: [
- {"_id": 0, "key": 1, "joined": [{"meta": 1, "val": 42}, {"meta": 2, "val": 17}]},
- {"_id": 1, "key": 2, "joined": [{"meta": 1, "val": 42}, {"meta": 2, "val": 17}]}
- ],
- extraErrorMsg: `Unexpected result of running pipeline ${tojson(lookupStage)}`
- });
- })();
-}
diff --git a/jstests/core/timeseries/timeseries_match_pushdown.js b/jstests/core/timeseries/timeseries_match_pushdown.js
deleted file mode 100644
index 93c841da9ec..00000000000
--- a/jstests/core/timeseries/timeseries_match_pushdown.js
+++ /dev/null
@@ -1,634 +0,0 @@
-/**
- * Tests that the $match stage followed by unpacking stage has been pushed down with correct
- * predicates.
- *
- * @tags: [
- * requires_timeseries,
- * requires_fcv_60,
- * does_not_support_stepdowns,
- * does_not_support_transactions,
- * directly_against_shardsvrs_incompatible,
- * ]
- */
-(function() {
-"use strict";
-
-load("jstests/libs/analyze_plan.js"); // For getAggPlanStages
-
-const coll = db.timeseries_match_pushdown;
-const timeField = 'time';
-const metaField = 'meta';
-const measureField = 'a';
-
-// The docs and queries are designed so that some buckets match the query entirely, some buckets
-// match the query partially, and some with no matches.
-const defaultDocs = [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: null, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: [1, 2, 3], [metaField]: 2}
-];
-
-/**
- * Setup the collection and run a $match query with the specified 'eventFilter' or a 'pipeline'.
- * Assert the 'wholeBucketFilter' is attached correctly to the unpacking stage, and has the expected
- * result 'expectedDocs'.
- */
-const runTest = function({docsToInsert, pipeline, eventFilter, wholeBucketFilter, expectedDocs}) {
- // Set up the collection. Each test will have it's own collection setup.
- coll.drop();
- assert.commandWorked(db.createCollection(coll.getName(), {timeseries: {timeField, metaField}}));
- // Insert documents into the collection.
- if (!docsToInsert) {
- docsToInsert = defaultDocs;
- }
- assert.commandWorked(coll.insert(docsToInsert));
-
- if (!pipeline) {
- pipeline = [{$match: eventFilter}];
- }
- const explain = assert.commandWorked(coll.explain().aggregate(pipeline));
- const unpackStages = getAggPlanStages(explain, '$_internalUnpackBucket');
- assert.eq(1,
- unpackStages.length,
- "Should only have a single $_internalUnpackBucket stage: " + tojson(explain));
- const unpackStage = unpackStages[0].$_internalUnpackBucket;
- assert.docEq(unpackStage.eventFilter, eventFilter, "Incorrect eventFilter: " + tojson(explain));
- if (wholeBucketFilter) {
- assert.docEq(unpackStage.wholeBucketFilter,
- wholeBucketFilter,
- "Incorrect wholeBucketFilter: " + tojson(explain));
- } else {
- assert(!unpackStage.wholeBucketFilter, "Incorrect wholeBucketFilter: " + tojson(explain));
- }
-
- const docs = coll.aggregate([...pipeline, {$sort: {time: 1}}]).toArray();
- assert.eq(docs.length, expectedDocs.length, "Incorrect docs: " + tojson(docs));
- docs.forEach((doc, i) => {
- // Do not need to check document _id, since checking time is already unique.
- delete doc._id;
- assert.docEq(doc, expectedDocs[i], "Incorrect docs: " + tojson(docs));
- });
-};
-
-const aTime = ISODate('2022-01-01T00:00:03');
-const bTime = ISODate('2022-01-01T00:00:07');
-const bMeta = 3;
-const aMeasure = 3;
-const minTimeField = `control.min.${timeField}`;
-const maxTimeField = `control.max.${timeField}`;
-
-// $gt on time
-runTest({
- eventFilter: {[timeField]: {$gt: aTime}},
- wholeBucketFilter: {[minTimeField]: {$gt: aTime}},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: null, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: [1, 2, 3], [metaField]: 2},
- ],
-});
-
-// $gt on measurement
-runTest({
- eventFilter: {[measureField]: {$gt: aMeasure}},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- ],
-});
-
-// $gt in $expr on time
-runTest({
- pipeline: [{$match: {$expr: {$gt: [`$${timeField}`, {$const: aTime}]}}}],
- eventFilter: {
- $and: [
- {[timeField]: {$_internalExprGt: aTime}},
- {$expr: {$gt: [`$${timeField}`, {$const: aTime}]}},
- ]
- },
- wholeBucketFilter: {
- $and: [
- {[minTimeField]: {$_internalExprGt: aTime}},
- {[minTimeField]: {$_internalExprGt: aTime}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: null, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: [1, 2, 3], [metaField]: 2},
- ],
-});
-
-// $gte on time
-runTest({
- eventFilter: {[timeField]: {$gte: aTime}},
- wholeBucketFilter: {[minTimeField]: {$gte: aTime}},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: null, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: [1, 2, 3], [metaField]: 2}
- ],
-});
-
-// $gte on measurement
-runTest({
- eventFilter: {[measureField]: {$gte: aMeasure}},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: [1, 2, 3], [metaField]: 2}
- ],
-});
-
-// $gte in $expr on time
-runTest({
- pipeline: [{$match: {$expr: {$gte: [`$${timeField}`, {$const: aTime}]}}}],
- eventFilter: {
- $and: [
- {[timeField]: {$_internalExprGte: aTime}},
- {$expr: {$gte: [`$${timeField}`, {$const: aTime}]}},
- ]
- },
- wholeBucketFilter: {
- $and: [
- {[minTimeField]: {$_internalExprGte: aTime}},
- {[minTimeField]: {$_internalExprGte: aTime}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: null, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: [1, 2, 3], [metaField]: 2}
- ],
-});
-
-// $lt on time
-runTest({
- eventFilter: {[timeField]: {$lt: aTime}},
- wholeBucketFilter: {[maxTimeField]: {$lt: aTime}},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- ],
-});
-
-// $lt on measurement
-runTest({
- eventFilter: {[measureField]: {$lt: aMeasure}},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: [1, 2, 3], [metaField]: 2}
- ],
-});
-
-// $lt in $expr on time
-runTest({
- pipeline: [{$match: {$expr: {$lt: [`$${timeField}`, {$const: aTime}]}}}],
- eventFilter: {
- $and: [
- {[timeField]: {$_internalExprLt: aTime}},
- {$expr: {$lt: [`$${timeField}`, {$const: aTime}]}},
- ]
- },
- wholeBucketFilter: {
- $and: [
- {[maxTimeField]: {$_internalExprLt: aTime}},
- {[maxTimeField]: {$_internalExprLt: aTime}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- ],
-});
-
-// $lte on time
-runTest({
- eventFilter: {[timeField]: {$lte: aTime}},
- wholeBucketFilter: {[maxTimeField]: {$lte: aTime}},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- ],
-});
-
-// $lte in $expr on time
-runTest({
- pipeline: [{$match: {$expr: {$lte: [`$${timeField}`, {$const: aTime}]}}}],
- eventFilter: {
- $and: [
- {[timeField]: {$_internalExprLte: aTime}},
- {$expr: {$lte: [`$${timeField}`, {$const: aTime}]}},
- ]
- },
- wholeBucketFilter: {
- $and: [
- {[maxTimeField]: {$_internalExprLte: aTime}},
- {[maxTimeField]: {$_internalExprLte: aTime}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- ],
-});
-
-// $lte on measurement
-runTest({
- eventFilter: {[measureField]: {$lte: aMeasure}},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: [1, 2, 3], [metaField]: 2}
- ],
-});
-
-// $eq on time
-runTest({
- eventFilter: {[timeField]: {$eq: aTime}},
- wholeBucketFilter: {$and: [{[minTimeField]: {$eq: aTime}}, {[maxTimeField]: {$eq: aTime}}]},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- ],
-});
-
-// $eq in $expr on time
-runTest({
- pipeline: [{$match: {$expr: {$eq: [`$${timeField}`, {$const: aTime}]}}}],
- eventFilter: {
- $and: [
- {[timeField]: {$_internalExprEq: aTime}},
- {$expr: {$eq: [`$${timeField}`, {$const: aTime}]}},
- ]
- },
- wholeBucketFilter: {
- $and: [
- {[minTimeField]: {$_internalExprEq: aTime}},
- {[maxTimeField]: {$_internalExprEq: aTime}},
- {[minTimeField]: {$_internalExprEq: aTime}},
- {[maxTimeField]: {$_internalExprEq: aTime}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- ],
-});
-
-// $eq on measurement
-runTest({
- docsToInsert: [
- ...defaultDocs,
- {[timeField]: ISODate('2022-01-01T00:00:06'), [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: null, [metaField]: 1}
- ],
- eventFilter: {[measureField]: {$eq: aMeasure}},
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: [1, 2, 3], [metaField]: 2}
- ],
-});
-
-// $and on time
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 3},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: 7, [metaField]: 3},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: 8, [metaField]: 3},
- ],
- eventFilter: {$and: [{[timeField]: {$gt: aTime}}, {[timeField]: {$lt: bTime}}]},
- wholeBucketFilter: {
- $and: [
- {[minTimeField]: {$gt: aTime}},
- {[maxTimeField]: {$lt: bTime}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 3},
- ],
-});
-
-//$or on time
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 3},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: 7, [metaField]: 3},
- ],
- eventFilter: {$or: [{[timeField]: {$lte: aTime}}, {[timeField]: {$gte: bTime}}]},
- wholeBucketFilter: {
- $or: [
- {[maxTimeField]: {$lte: aTime}},
- {[minTimeField]: {$gte: bTime}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: 7, [metaField]: 3},
- ],
-});
-
-// $match on time and meta
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 3},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: 7, [metaField]: 3},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: 8, [metaField]: 3},
- ],
- pipeline: [{$match: {$and: [{[timeField]: {$gt: aTime}}, {[metaField]: {$lte: bMeta}}]}}],
- eventFilter: {[timeField]: {$gt: aTime}},
- wholeBucketFilter: {
- [minTimeField]: {$gt: aTime},
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 3},
- {[timeField]: ISODate('2022-01-01T00:00:07'), [measureField]: 7, [metaField]: 3},
- {[timeField]: ISODate('2022-01-01T00:00:08'), [measureField]: 8, [metaField]: 3},
- ],
-});
-
-// $match on time and meta inside $expr. There should not be a wholeBucketFilter, since the entire
-// $and expression cannot be rewritten as a MatchExpression, and for $expr predicates we only
-// generate a wholeBucketFilter for single predicates on the timeField.
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:03'), [metaField]: 1, [measureField]: 3},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [metaField]: 1, [measureField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [metaField]: 2, [measureField]: 3},
- ],
- pipeline: [{
- $match: {
- $expr: {
- $and:
- [{$eq: [`$${metaField}`, `$${measureField}`]}, {$gt: [`$${timeField}`, aTime]}]
- }
- }
- }],
- eventFilter: {
- $and: [
- {[timeField]: {$_internalExprGt: aTime}},
- {
- $expr: {
- $and: [
- {$eq: [`$${metaField}`, `$${measureField}`]},
- {$gt: [`$${timeField}`, {$const: aTime}]}
- ]
- }
- },
- ]
- },
- expectedDocs: [{[timeField]: ISODate('2022-01-01T00:00:04'), [metaField]: 1, [measureField]: 1}]
-});
-
-// $match on time and meta inside $expr. The entire $and expression can be rewritten into a
-// MatchExpression. However, for $expr predicates we only generate a wholeBucketFilter for single
-// predicates on the timeField.
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:03'), [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [metaField]: 2},
- ],
- pipeline:
- [{$match: {$expr: {$and: [{$eq: [`$${metaField}`, 1]}, {$gt: [`$${timeField}`, aTime]}]}}}],
- eventFilter: {
- $and: [
- {[timeField]: {$_internalExprGt: aTime}},
- {
- $expr: {
- $and: [
- {$eq: [`$${metaField}`, {$const: 1}]},
- {$gt: [`$${timeField}`, {$const: aTime}]}
- ]
- }
- },
- {[metaField]: {$_internalExprEq: 1}},
- {[timeField]: {$_internalExprGt: aTime}},
- ]
- },
- expectedDocs: [{[timeField]: ISODate('2022-01-01T00:00:04'), [metaField]: 1}]
-});
-
-// $match on time or meta
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 3},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 4},
- ],
- eventFilter: {$or: [{[timeField]: {$lte: aTime}}, {[metaField]: {$gt: bMeta}}]},
- wholeBucketFilter: {
- $or: [
- {[maxTimeField]: {$lte: aTime}},
- {[metaField]: {$gt: bMeta}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 4},
- ],
-});
-
-// double $match
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 3},
- ],
- pipeline: [{$match: {[timeField]: {$gt: aTime}}}, {$match: {[timeField]: {$lt: bTime}}}],
- eventFilter: {$and: [{[timeField]: {$gt: aTime}}, {[timeField]: {$lt: bTime}}]},
- wholeBucketFilter: {
- $and: [
- {[minTimeField]: {$gt: aTime}},
- {[maxTimeField]: {$lt: bTime}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 3},
- ],
-});
-
-// triple $match
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 0},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [measureField]: 4, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 3},
- ],
- pipeline: [
- {$match: {[timeField]: {$gt: aTime}}},
- {$match: {[timeField]: {$lt: bTime}}},
- {$match: {[timeField]: {$lt: aTime}}},
- ],
- eventFilter: {
- $and:
- [{[timeField]: {$gt: aTime}}, {[timeField]: {$lt: bTime}}, {[timeField]: {$lt: aTime}}]
- },
- wholeBucketFilter: {
- $and: [
- {[minTimeField]: {$gt: aTime}},
- {[maxTimeField]: {$lt: bTime}},
- {[maxTimeField]: {$lt: aTime}},
- ]
- },
- expectedDocs: [],
-});
-
-// $and inside $expr with comparison on meta and measurement. There should not be a
-// wholeBucketFilter, since the entire $and expression cannot be rewritten as a MatchExpression, and
-// for $expr predicates we only generate a wholeBucketFilter for single predicates on the timeField.
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:00'), [measureField]: 0, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 3},
- ],
- pipeline: [{
- $match: {
- $expr:
- {$and: [{$lt: [`$${measureField}`, `$${metaField}`]}, {$gt: [`$${metaField}`, 1]}]}
- }
- }],
- eventFilter: {
- $and: [
- {"meta": {$_internalExprGt: 1}},
- {
- $expr: {
- $and: [
- {$lt: [`$${measureField}`, `$${metaField}`]},
- {$gt: [`$${metaField}`, {$const: 1}]}
- ]
- }
- }
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [metaField]: 2},
- ]
-});
-
-// Same test as above, but the entire $and expression can be rewritten as a MatchExpression.
-// However, for $expr predicates we only generate a wholeBucketFilter for single predicates on the
-// timeField.
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:00'), [measureField]: 0, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: null, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:06'), [measureField]: 6, [metaField]: 3},
- ],
- pipeline:
- [{$match: {$expr: {$and: [{$gte: [`$${measureField}`, 2]}, {$lt: [`$${metaField}`, 3]}]}}}],
- eventFilter: {
- $and: [
- {[measureField]: {$_internalExprGte: 2}},
- {
- $expr: {
- $and: [
- {$gte: [`$${measureField}`, {$const: 2}]},
- {$lt: [`$${metaField}`, {$const: 3}]}
- ]
- }
- },
- {[measureField]: {$_internalExprGte: 2}},
- {[metaField]: {$_internalExprLt: 3}},
- ]
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 2},
- ]
-});
-
-// Same test as above but with $or and different comparison operators.
-runTest({
- docsToInsert: [
- {[timeField]: ISODate('2022-01-01T00:00:00'), [measureField]: 0, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:05'), [measureField]: 5, [metaField]: 3},
- ],
- pipeline: [{
- $match: {
- $expr:
- {$or: [{$lt: [`$${measureField}`, `$${metaField}`]}, {$lte: [`$${metaField}`, 2]}]}
- }
- }],
- eventFilter: {
- $expr: {
- $or: [
- {$lt: [`$${measureField}`, `$${metaField}`]},
- {$lte: [`$${metaField}`, {$const: 2}]}
- ]
- }
- },
- expectedDocs: [
- {[timeField]: ISODate('2022-01-01T00:00:00'), [measureField]: 0, [metaField]: 1},
- {[timeField]: ISODate('2022-01-01T00:00:01'), [measureField]: 1, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:02'), [measureField]: 2, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:03'), [measureField]: 3, [metaField]: 2},
- {[timeField]: ISODate('2022-01-01T00:00:04'), [metaField]: 2},
- ]
-});
-})();
diff --git a/jstests/core/timeseries/timeseries_match_pushdown_with_project.js b/jstests/core/timeseries/timeseries_match_pushdown_with_project.js
deleted file mode 100644
index 2d8e872c33a..00000000000
--- a/jstests/core/timeseries/timeseries_match_pushdown_with_project.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- * Tests that the unpacking stage has correct unpacking behaviour when $match is pushed into it.
- *
- * @tags: [
- * requires_timeseries,
- * requires_fcv_60,
- * does_not_support_stepdowns,
- * does_not_support_transactions,
- * directly_against_shardsvrs_incompatible,
- * ]
- */
-(function() {
-"use strict";
-
-load("jstests/libs/analyze_plan.js"); // For getAggPlanStages
-
-const coll = db.timeseries_match_pushdown_with_project;
-coll.drop();
-
-const timeField = 'time';
-const metaField = 'meta';
-assert.commandWorked(db.createCollection(coll.getName(), {timeseries: {timeField, metaField}}));
-
-const aTime = ISODate('2022-01-01T00:00:00');
-assert.commandWorked(coll.insert([
- {[timeField]: aTime, a: 1, b: 1, _id: 1},
- {[timeField]: aTime, a: 2, b: 2, _id: 2},
- {[timeField]: aTime, a: 3, b: 3, _id: 3},
- {[timeField]: aTime, a: 4, b: 4, _id: 4},
- {[timeField]: aTime, a: 5, b: 5, _id: 5},
- {[timeField]: aTime, a: 6, b: 6, _id: 6},
- {[timeField]: aTime, a: 7, b: 7, _id: 7},
- {[timeField]: aTime, a: 8, b: 8, _id: 8},
- {[timeField]: aTime, a: 9, b: 9, _id: 9},
-]));
-
-/**
- * Runs a 'pipeline', asserts the bucket unpacking 'behaviour' (either include or exclude) is
- * expected.
- */
-const runTest = function({pipeline, behaviour, expectedDocs}) {
- const explain = assert.commandWorked(coll.explain().aggregate(pipeline));
- const unpackStages = getAggPlanStages(explain, '$_internalUnpackBucket');
- assert.eq(1,
- unpackStages.length,
- "Should only have a single $_internalUnpackBucket stage: " + tojson(explain));
- const unpackStage = unpackStages[0].$_internalUnpackBucket;
- if (behaviour.include) {
- assert(unpackStage.include,
- "Unpacking stage must have 'include' behaviour: " + tojson(explain));
- assert.sameMembers(behaviour.include, unpackStage.include);
- }
- if (behaviour.exclude) {
- assert(unpackStage.exclude,
- "Unpacking stage must have 'exclude' behaviour: " + tojson(explain));
- assert.sameMembers(behaviour.exclude, unpackStage.exclude);
- }
-
- const docs = coll.aggregate([...pipeline, {$sort: {a: 1, b: 1, _id: 1}}]).toArray();
- assert.eq(docs.length, expectedDocs.length, "Incorrect docs: " + tojson(docs));
- docs.forEach((doc, i) => {
- assert.docEq(doc, expectedDocs[i], "Incorrect docs: " + tojson(docs));
- });
-};
-
-runTest({
- pipeline: [{$match: {a: {$gt: 5}}}, {$project: {b: 1}}],
- behaviour: {include: ['_id', 'a', 'b']},
- expectedDocs: [
- {b: 6, _id: 6},
- {b: 7, _id: 7},
- {b: 8, _id: 8},
- {b: 9, _id: 9},
- ],
-});
-
-runTest({
- pipeline: [{$match: {a: {$gt: 5}}}, {$project: {_id: 0, b: 1}}],
- behaviour: {include: ['a', 'b']},
- expectedDocs: [
- {b: 6},
- {b: 7},
- {b: 8},
- {b: 9},
- ],
-});
-
-runTest({
- pipeline: [{$match: {a: {$gt: 5}}}, {$project: {a: 1}}],
- behaviour: {include: ['_id', 'a']},
- expectedDocs: [
- {a: 6, _id: 6},
- {a: 7, _id: 7},
- {a: 8, _id: 8},
- {a: 9, _id: 9},
- ],
-});
-
-runTest({
- pipeline: [{$match: {a: {$gt: 5}}}, {$project: {_id: 0, a: 1}}],
- behaviour: {include: ['a']},
- expectedDocs: [
- {a: 6},
- {a: 7},
- {a: 8},
- {a: 9},
- ],
-});
-
-runTest({
- pipeline: [{$match: {a: {$gt: 5}}}, {$project: {a: 0}}],
- behaviour: {exclude: []},
- expectedDocs: [
- {[timeField]: aTime, b: 6, _id: 6},
- {[timeField]: aTime, b: 7, _id: 7},
- {[timeField]: aTime, b: 8, _id: 8},
- {[timeField]: aTime, b: 9, _id: 9},
- ],
-});
-
-runTest({
- pipeline: [{$match: {a: {$gt: 5}}}, {$project: {b: 0}}],
- behaviour: {exclude: []},
- expectedDocs: [
- {[timeField]: aTime, a: 6, _id: 6},
- {[timeField]: aTime, a: 7, _id: 7},
- {[timeField]: aTime, a: 8, _id: 8},
- {[timeField]: aTime, a: 9, _id: 9},
- ],
-});
-})();
diff --git a/jstests/core/timeseries/timeseries_merge.js b/jstests/core/timeseries/timeseries_merge.js
index fb6a23df803..59d4dbee889 100644
--- a/jstests/core/timeseries/timeseries_merge.js
+++ b/jstests/core/timeseries/timeseries_merge.js
@@ -6,7 +6,6 @@
* does_not_support_stepdowns,
* does_not_support_transactions,
* requires_timeseries,
- * references_foreign_collection,
* ]
*/
(function() {
diff --git a/jstests/core/timeseries/timeseries_metric_index_2dsphere.js b/jstests/core/timeseries/timeseries_metric_index_2dsphere.js
index 7096ace9513..e47119b5bbd 100644
--- a/jstests/core/timeseries/timeseries_metric_index_2dsphere.js
+++ b/jstests/core/timeseries/timeseries_metric_index_2dsphere.js
@@ -18,9 +18,8 @@
load("jstests/core/timeseries/libs/timeseries.js");
load("jstests/libs/analyze_plan.js");
-load("jstests/libs/feature_flag_util.js");
-if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
return;
}
diff --git a/jstests/core/timeseries/timeseries_metric_index_ascending_descending.js b/jstests/core/timeseries/timeseries_metric_index_ascending_descending.js
index 8a827b9d07b..bf1dc10e625 100644
--- a/jstests/core/timeseries/timeseries_metric_index_ascending_descending.js
+++ b/jstests/core/timeseries/timeseries_metric_index_ascending_descending.js
@@ -14,10 +14,9 @@
"use strict";
load("jstests/core/timeseries/libs/timeseries.js");
-load("jstests/libs/feature_flag_util.js");
load("jstests/libs/fixture_helpers.js");
-if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
jsTestLog(
"Skipped test as the featureFlagTimeseriesMetricIndexes feature flag is not enabled.");
return;
diff --git a/jstests/core/timeseries/timeseries_metric_index_compound.js b/jstests/core/timeseries/timeseries_metric_index_compound.js
index c81f9a4c53c..2ecc4732b70 100644
--- a/jstests/core/timeseries/timeseries_metric_index_compound.js
+++ b/jstests/core/timeseries/timeseries_metric_index_compound.js
@@ -13,9 +13,8 @@
"use strict";
load("jstests/core/timeseries/libs/timeseries.js");
-load("jstests/libs/feature_flag_util.js");
-if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
jsTestLog(
"Skipped test as the featureFlagTimeseriesMetricIndexes feature flag is not enabled.");
return;
diff --git a/jstests/core/timeseries/timeseries_predicates.js b/jstests/core/timeseries/timeseries_predicates.js
index ca78464cb31..a273cc8b128 100644
--- a/jstests/core/timeseries/timeseries_predicates.js
+++ b/jstests/core/timeseries/timeseries_predicates.js
@@ -17,7 +17,7 @@ const tsColl = db.timeseries_predicates_timeseries;
coll.drop();
tsColl.drop();
assert.commandWorked(
- db.createCollection(tsColl.getName(), {timeseries: {timeField: 'time', metaField: 'mt'}}));
+ db.createCollection(tsColl.getName(), {timeseries: {timeField: 'time', metaField: 'meta'}}));
const bucketsColl = db.getCollection('system.buckets.' + tsColl.getName());
// Test that 'predicate' behaves correctly on the example documents,
@@ -86,18 +86,18 @@ checkAllBucketings({x: {$exists: true}}, [
// Test $or...
{
- // ... on metric + mt.
+ // ... on metric + meta.
checkAllBucketings({
$or: [
{x: {$lt: 0}},
- {'mt.y': {$gt: 0}},
+ {'meta.y': {$gt: 0}},
]
},
[
- {x: +1, mt: {y: -1}},
- {x: +1, mt: {y: +1}},
- {x: -1, mt: {y: -1}},
- {x: -1, mt: {y: +1}},
+ {x: +1, meta: {y: -1}},
+ {x: +1, meta: {y: +1}},
+ {x: -1, meta: {y: -1}},
+ {x: -1, meta: {y: +1}},
]);
// ... when one argument can't be pushed down.
@@ -131,18 +131,18 @@ checkAllBucketings({x: {$exists: true}}, [
// Test $and...
{
- // ... on metric + mt.
+ // ... on metric + meta.
checkAllBucketings({
$and: [
{x: {$lt: 0}},
- {'mt.y': {$gt: 0}},
+ {'meta.y': {$gt: 0}},
]
},
[
- {x: +1, mt: {y: -1}},
- {x: +1, mt: {y: +1}},
- {x: -1, mt: {y: -1}},
- {x: -1, mt: {y: +1}},
+ {x: +1, meta: {y: -1}},
+ {x: +1, meta: {y: +1}},
+ {x: -1, meta: {y: -1}},
+ {x: -1, meta: {y: +1}},
]);
// ... when one argument can't be pushed down.
@@ -180,28 +180,28 @@ checkAllBucketings({
$or: [
{
$and: [
- {'mt.a': {$gt: 0}},
+ {'meta.a': {$gt: 0}},
{'x': {$lt: 0}},
]
},
{
$and: [
- {'mt.b': {$gte: 0}},
+ {'meta.b': {$gte: 0}},
{time: {$gt: ISODate('2020-01-01')}},
]
},
]
},
[
- {mt: {a: -1, b: -1}, x: -1, time: ISODate('2020-02-01')},
- {mt: {a: -1, b: -1}, x: -1, time: ISODate('2019-12-31')},
- {mt: {a: -1, b: -1}, x: +1, time: ISODate('2020-02-01')},
- {mt: {a: -1, b: -1}, x: +1, time: ISODate('2019-12-31')},
+ {meta: {a: -1, b: -1}, x: -1, time: ISODate('2020-02-01')},
+ {meta: {a: -1, b: -1}, x: -1, time: ISODate('2019-12-31')},
+ {meta: {a: -1, b: -1}, x: +1, time: ISODate('2020-02-01')},
+ {meta: {a: -1, b: -1}, x: +1, time: ISODate('2019-12-31')},
- {mt: {a: +1, b: -1}, x: -1, time: ISODate('2020-02-01')},
- {mt: {a: +1, b: -1}, x: -1, time: ISODate('2019-12-31')},
- {mt: {a: +1, b: -1}, x: +1, time: ISODate('2020-02-01')},
- {mt: {a: +1, b: -1}, x: +1, time: ISODate('2019-12-31')},
+ {meta: {a: +1, b: -1}, x: -1, time: ISODate('2020-02-01')},
+ {meta: {a: +1, b: -1}, x: -1, time: ISODate('2019-12-31')},
+ {meta: {a: +1, b: -1}, x: +1, time: ISODate('2020-02-01')},
+ {meta: {a: +1, b: -1}, x: +1, time: ISODate('2019-12-31')},
]);
// Test nested $and / $or where some leaf predicates cannot be pushed down.
@@ -209,72 +209,72 @@ checkAllBucketings({
$or: [
{
$and: [
- {'mt.a': {$gt: 0}},
+ {'meta.a': {$gt: 0}},
{'x': {$exists: false}},
]
},
{
$and: [
- {'mt.b': {$gte: 0}},
+ {'meta.b': {$gte: 0}},
{time: {$gt: ISODate('2020-01-01')}},
]
},
]
},
[
- {mt: {a: -1, b: -1}, time: ISODate('2020-02-01')},
- {mt: {a: -1, b: -1}, time: ISODate('2019-12-31')},
- {mt: {a: -1, b: -1}, x: 'asdf', time: ISODate('2020-02-01')},
- {mt: {a: -1, b: -1}, x: 'asdf', time: ISODate('2019-12-31')},
+ {meta: {a: -1, b: -1}, time: ISODate('2020-02-01')},
+ {meta: {a: -1, b: -1}, time: ISODate('2019-12-31')},
+ {meta: {a: -1, b: -1}, x: 'asdf', time: ISODate('2020-02-01')},
+ {meta: {a: -1, b: -1}, x: 'asdf', time: ISODate('2019-12-31')},
- {mt: {a: +1, b: -1}, time: ISODate('2020-02-01')},
- {mt: {a: +1, b: -1}, time: ISODate('2019-12-31')},
- {mt: {a: +1, b: -1}, x: 'asdf', time: ISODate('2020-02-01')},
- {mt: {a: +1, b: -1}, x: 'asdf', time: ISODate('2019-12-31')},
+ {meta: {a: +1, b: -1}, time: ISODate('2020-02-01')},
+ {meta: {a: +1, b: -1}, time: ISODate('2019-12-31')},
+ {meta: {a: +1, b: -1}, x: 'asdf', time: ISODate('2020-02-01')},
+ {meta: {a: +1, b: -1}, x: 'asdf', time: ISODate('2019-12-31')},
]);
-// Test $exists on mt, inside $or.
+// Test $exists on meta, inside $or.
checkAllBucketings({
$or: [
- {"mt.a": {$exists: true}},
+ {"meta.a": {$exists: true}},
{"x": {$gt: 2}},
]
},
[
- {mt: {a: 1}, x: 1},
- {mt: {a: 2}, x: 2},
- {mt: {a: 3}, x: 3},
- {mt: {a: 4}, x: 4},
- {mt: {}, x: 1},
- {mt: {}, x: 2},
- {mt: {}, x: 3},
- {mt: {}, x: 4},
+ {meta: {a: 1}, x: 1},
+ {meta: {a: 2}, x: 2},
+ {meta: {a: 3}, x: 3},
+ {meta: {a: 4}, x: 4},
+ {meta: {}, x: 1},
+ {meta: {}, x: 2},
+ {meta: {}, x: 3},
+ {meta: {}, x: 4},
]);
-// Test $in on mt, inside $or.
+// Test $in on meta, inside $or.
checkAllBucketings({
$or: [
- {"mt.a": {$in: [1, 3]}},
+ {"meta.a": {$in: [1, 3]}},
{"x": {$gt: 2}},
]
},
[
- {mt: {a: 1}, x: 1},
- {mt: {a: 2}, x: 2},
- {mt: {a: 3}, x: 3},
- {mt: {a: 4}, x: 4},
- {mt: {}, x: 1},
- {mt: {}, x: 2},
- {mt: {}, x: 3},
- {mt: {}, x: 4},
+ {meta: {a: 1}, x: 1},
+ {meta: {a: 2}, x: 2},
+ {meta: {a: 3}, x: 3},
+ {meta: {a: 4}, x: 4},
+ {meta: {}, x: 1},
+ {meta: {}, x: 2},
+ {meta: {}, x: 3},
+ {meta: {}, x: 4},
]);
-// Test geo predicates on mt, inside $or.
+// Test geo predicates on meta, inside $or.
for (const pred of ['$geoWithin', '$geoIntersects']) {
checkAllBucketings({
$or: [
{
- "mt.location": {
+ "meta.location": {
[pred]: {
$geometry: {
type: "Polygon",
@@ -293,90 +293,66 @@ for (const pred of ['$geoWithin', '$geoIntersects']) {
]
},
[
- {mt: {location: [1, 1]}, x: 1},
- {mt: {location: [1, 1]}, x: 2},
- {mt: {location: [1, 1]}, x: 3},
- {mt: {location: [1, 1]}, x: 4},
- {mt: {location: [5, 5]}, x: 1},
- {mt: {location: [5, 5]}, x: 2},
- {mt: {location: [5, 5]}, x: 3},
- {mt: {location: [5, 5]}, x: 4},
+ {meta: {location: [1, 1]}, x: 1},
+ {meta: {location: [1, 1]}, x: 2},
+ {meta: {location: [1, 1]}, x: 3},
+ {meta: {location: [1, 1]}, x: 4},
+ {meta: {location: [5, 5]}, x: 1},
+ {meta: {location: [5, 5]}, x: 2},
+ {meta: {location: [5, 5]}, x: 3},
+ {meta: {location: [5, 5]}, x: 4},
]);
}
-// Test $mod on mt, inside $or.
+// Test $mod on meta, inside $or.
// $mod is an example of a predicate that we don't handle specially in time-series optimizations:
// it can be pushed down if and only if it's on a metadata field.
checkAllBucketings({
$or: [
- {"mt.a": {$mod: [2, 0]}},
+ {"meta.a": {$mod: [2, 0]}},
{"x": {$gt: 4}},
]
},
[
- {mt: {a: 1}, x: 1},
- {mt: {a: 2}, x: 2},
- {mt: {a: 3}, x: 3},
- {mt: {a: 4}, x: 4},
- {mt: {a: 5}, x: 5},
- {mt: {a: 6}, x: 6},
- {mt: {a: 7}, x: 7},
- {mt: {a: 8}, x: 8},
+ {meta: {a: 1}, x: 1},
+ {meta: {a: 2}, x: 2},
+ {meta: {a: 3}, x: 3},
+ {meta: {a: 4}, x: 4},
+ {meta: {a: 5}, x: 5},
+ {meta: {a: 6}, x: 6},
+ {meta: {a: 7}, x: 7},
+ {meta: {a: 8}, x: 8},
]);
-// Test $elemMatch on mt, inside $or.
+// Test $elemMatch on meta, inside $or.
checkAllBucketings({
$or: [
- {"mt.a": {$elemMatch: {b: 3}}},
+ {"meta.a": {$elemMatch: {b: 3}}},
{"x": {$gt: 4}},
]
},
[
- {x: 1, mt: {a: []}},
- {x: 2, mt: {a: [{b: 2}]}},
- {x: 3, mt: {a: [{b: 3}]}},
- {x: 4, mt: {a: [{b: 2}, {b: 3}]}},
- {x: 5, mt: {a: []}},
- {x: 6, mt: {a: [{b: 2}]}},
- {x: 7, mt: {a: [{b: 3}]}},
- {x: 8, mt: {a: [{b: 2}, {b: 3}]}},
+ {x: 1, meta: {a: []}},
+ {x: 2, meta: {a: [{b: 2}]}},
+ {x: 3, meta: {a: [{b: 3}]}},
+ {x: 4, meta: {a: [{b: 2}, {b: 3}]}},
+ {x: 5, meta: {a: []}},
+ {x: 6, meta: {a: [{b: 2}]}},
+ {x: 7, meta: {a: [{b: 3}]}},
+ {x: 8, meta: {a: [{b: 2}, {b: 3}]}},
]);
checkAllBucketings({
$or: [
- {"mt.a": {$elemMatch: {b: 2, c: 3}}},
+ {"meta.a": {$elemMatch: {b: 2, c: 3}}},
{"x": {$gt: 3}},
]
},
[
- {x: 1, mt: {a: []}},
- {x: 2, mt: {a: [{b: 2, c: 3}]}},
- {x: 3, mt: {a: [{b: 2}, {c: 3}]}},
- {x: 4, mt: {a: []}},
- {x: 5, mt: {a: [{b: 2, c: 3}]}},
- {x: 6, mt: {a: [{b: 2}, {c: 3}]}},
+ {x: 1, meta: {a: []}},
+ {x: 2, meta: {a: [{b: 2, c: 3}]}},
+ {x: 3, meta: {a: [{b: 2}, {c: 3}]}},
+ {x: 4, meta: {a: []}},
+ {x: 5, meta: {a: [{b: 2, c: 3}]}},
+ {x: 6, meta: {a: [{b: 2}, {c: 3}]}},
]);
-
-// Test a standalone $elemMatch on mt.
-checkAllBucketings({"mt.a": {$elemMatch: {b: 3}}}, [
- {mt: {a: []}},
- {mt: {a: [{b: 2}]}},
- {mt: {a: [{b: 3}]}},
- {mt: {a: [{b: 2}, {b: 3}]}},
- {mt: {a: []}},
- {mt: {a: [{b: 2}]}},
- {mt: {a: [{b: 3}]}},
- {mt: {a: [{b: 2}, {b: 3}]}},
-]);
-
-// Test a standalone $size on mt.
-checkAllBucketings({"mt.a": {$size: 1}}, [
- {mt: {a: []}},
- {mt: {a: [{b: 2}]}},
- {mt: {a: [{b: 3}]}},
- {mt: {a: [{b: 2}, {b: 3}]}},
- {mt: {a: []}},
- {mt: {a: [{b: 2}]}},
- {mt: {a: [{b: 3}]}},
- {mt: {a: [{b: 2}, {b: 3}]}},
-]);
})();
diff --git a/jstests/core/timeseries/timeseries_project.js b/jstests/core/timeseries/timeseries_project.js
index b735a8a3b66..9375f06240d 100644
--- a/jstests/core/timeseries/timeseries_project.js
+++ b/jstests/core/timeseries/timeseries_project.js
@@ -4,7 +4,7 @@
* @tags: [
* does_not_support_stepdowns,
* does_not_support_transactions,
- * requires_fcv_60,
+ * requires_fcv_53,
* ]
*/
(function() {
@@ -97,7 +97,6 @@ const doc = {
time: new Date("2019-10-11T14:39:18.670Z"),
x: 5,
a: 3,
- obj: {a: 3},
};
assert.commandWorked(tsColl.insert(doc));
assert.commandWorked(regColl.insert(doc));
@@ -108,192 +107,10 @@ let tsDoc = tsColl.aggregate(pipeline).toArray();
let regDoc = regColl.aggregate(pipeline).toArray();
assert.docEq(tsDoc, regDoc);
-pipeline = [{$project: {_id: 0, obj: "$x", b: {$add: ["$obj.a", 1]}}}];
-tsDoc = tsColl.aggregate(pipeline).toArray();
-regDoc = regColl.aggregate(pipeline).toArray();
-assert.docEq(tsDoc, regDoc);
-
// Test $addFields.
pipeline = [{$addFields: {a: "$x", b: "$a"}}, {$project: {_id: 0}}];
tsDoc = tsColl.aggregate(pipeline).toArray();
regDoc = regColl.aggregate(pipeline).toArray();
assert.docEq(tsDoc, regDoc);
-
-pipeline = [{$addFields: {obj: "$x", b: {$add: ["$obj.a", 1]}}}, {$project: {_id: 0}}];
-tsDoc = tsColl.aggregate(pipeline).toArray();
-regDoc = regColl.aggregate(pipeline).toArray();
-assert.docEq(tsDoc, regDoc);
-
-pipeline = [{$project: {a: 1, _id: 0}}, {$project: {newMeta: "$x"}}];
-tsDoc = tsColl.aggregate(pipeline).toArray();
-regDoc = regColl.aggregate(pipeline).toArray();
-assert.docEq(tsDoc, regDoc);
-})();
-
-// Test that an includes projection that doesn't include previously included computed meta fields
-// outputs correctly.
-(function testIncludeComputedMetaFieldThenProjectWithoutComputedMetaField() {
- coll.drop();
- assert.commandWorked(
- db.createCollection(coll.getName(), {timeseries: {timeField: 'time', metaField: 'tag'}}));
-
- const doc = {_id: 0, time: ISODate("2024-01-01T00:00:00.000Z"), tag: {field: "A"}};
- assert.commandWorked(coll.insert(doc));
- let result = {};
-
- // Added field which uses meta should not be in the result.
- result =
- coll.aggregate(
- [{$addFields: {time: {$dateFromParts: {year: "$tag.none"}}}}, {$project: {tag: 1}}])
- .toArray();
- assert.docEq([{"tag": {"field": "A"}, "_id": 0}], result);
-
- // Test with non-null value.
- result = coll.aggregate([{$addFields: {time: {$toLower: "$tag.field"}}}, {$project: {tag: 1}}])
- .toArray();
- assert.docEq([{"tag": {"field": "A"}, "_id": 0}], result);
-
- // Testing with $match between $addFields and $project.
- result = coll.aggregate([
- {$addFields: {time: {$dateFromParts: {year: "$tag.none"}}}},
- {$match: {tag: {field: "A"}}},
- {$project: {tag: 1}}
- ])
- .toArray();
- assert.docEq([{"tag": {field: "A"}, "_id": 0}], result);
-
- // Test with non-null value.
- result =
- coll.aggregate(
- [{$addFields: {time: "$tag.field"}}, {$match: {time: "A"}}, {$project: {tag: 1}}])
- .toArray();
- assert.docEq([{"tag": {field: "A"}, "_id": 0}], result);
-
- // Testing with $project after $project.
- result = coll.aggregate([{$project: {tag: 1}}, {$project: {time: 1}}]).toArray();
- assert.docEq([{"_id": 0}], result);
-
- // Testing with $set.
- result = coll.aggregate([{$set: {tag: "$tag.field"}}, {$project: {time: 1}}]).toArray();
- assert.docEq([{"_id": 0, "time": ISODate("2024-01-01T00:00:00Z")}], result);
-
- // Test that computedMetaFields that are included by the $project are still included.
- result = coll.aggregate([
- {$addFields: {hi: {$dateFromParts: {year: "$tag.none"}}}},
- {$addFields: {bye: {$dateFromParts: {year: "$tag.none"}}}},
- {$project: {hi: 1}}
- ])
- .toArray();
- assert.docEq([{"_id": 0, "hi": null}], result);
-
- // Test with non-null value.
- result = coll.aggregate([
- {$addFields: {hi: "$tag.field"}},
- {$addFields: {bye: "$tag.field"}},
- {$project: {hi: 1}}
- ])
- .toArray();
- assert.docEq([{"_id": 0, "hi": "A"}], result);
-
- // Test that $project that replaces field that is used works.
- result = coll.aggregate([
- {$addFields: {hello: "$tag.field"}},
- {$project: {newTime: "$time", time: "$tag.field"}}
- ])
- .toArray();
-
- assert.docEq([{"_id": 0, newTime: ISODate("2024-01-01T00:00:00.000Z"), time: "A"}], result);
-
- // Test adding fields and including one of them.
- result = coll.aggregate([
- {$addFields: {a: {$toLower: "$tag.field"}}},
- {$addFields: {b: {$toUpper: "$tag.field"}}},
- {$project: {b: 1}}
- ])
- .toArray();
- assert.docEq([{b: "A", "_id": 0}], result);
-})();
-
-// Test that an excludes projection that excludes previously included computed meta fields
-// outputs correctly.
-(function testIncludeComputedMetaFieldThenExcludeComputedMetaField() {
- coll.drop();
- assert.commandWorked(
- db.createCollection(coll.getName(), {timeseries: {timeField: 'time', metaField: 'tag'}}));
-
- const doc = {_id: 0, time: ISODate("2024-01-01T00:00:00.000Z"), tag: {field: "A"}};
- assert.commandWorked(coll.insert(doc));
- let result = {};
-
- // Excluded '_computedMetaProjField' should not be included.
- result = coll.aggregate([
- {$addFields: {hello: {$dateFromParts: {year: "$tag.none"}}}},
- {$project: {hello: 0}}
- ])
- .toArray();
- assert.docEq([{"time": ISODate("2024-01-01T00:00:00Z"), "tag": {"field": "A"}, "_id": 0}],
- result);
-
- // Test with non-null value.
- result = coll.aggregate([{$addFields: {time: {$toLower: "$tag.field"}}}, {$project: {time: 0}}])
- .toArray();
- assert.docEq([{"tag": {"field": "A"}, "_id": 0}], result);
-
- // Testing with $match between $addFields and $project.
- result = coll.aggregate([
- {$addFields: {time: {$dateFromParts: {year: "$tag.none"}}}},
- {$match: {tag: {field: "A"}}},
- {$project: {time: 0}}
- ])
- .toArray();
- assert.docEq([{"tag": {field: "A"}, "_id": 0}], result);
-
- // Test with non-null value.
- result =
- coll.aggregate(
- [{$addFields: {time: "$tag.field"}}, {$match: {time: "A"}}, {$project: {time: 0}}])
- .toArray();
- assert.docEq([{"tag": {field: "A"}, "_id": 0}], result);
-
- // Testing with exclude $project after include $project.
- result = coll.aggregate([{$project: {tag: 1}}, {$project: {tag: 0}}]).toArray();
- assert.docEq([{"_id": 0}], result);
-
- // Testing with $set.
- result = coll.aggregate([{$set: {tag: "$tag.field"}}, {$project: {tag: 0}}]).toArray();
- assert.docEq([{"time": ISODate("2024-01-01T00:00:00Z"), "_id": 0}], result);
-
- // Exclude one added field.
- result = coll.aggregate([
- {$addFields: {hi: {$dateFromParts: {year: "$tag.none"}}}},
- {$addFields: {bye: {$dateFromParts: {year: "$tag.none"}}}},
- {$project: {hi: 0}}
- ])
- .toArray();
- assert.docEq(
- [{"time": ISODate("2024-01-01T00:00:00Z"), "tag": {"field": "A"}, "_id": 0, "bye": null}],
- result);
-
- // Test with non-null value.
- result = coll.aggregate([
- {$addFields: {hi: "$tag.field"}},
- {$addFields: {bye: "$tag.field"}},
- {$project: {hi: 0}}
- ])
- .toArray();
- assert.docEq(
- [{"time": ISODate("2024-01-01T00:00:00Z"), "tag": {"field": "A"}, "_id": 0, "bye": "A"}],
- result);
-
- // Test adding fields and excluding one of them.
- result = coll.aggregate([
- {$addFields: {a: {$toLower: "$tag.field"}}},
- {$addFields: {b: {$toUpper: "$tag.field"}}},
- {$project: {b: 0}}
- ])
- .toArray();
- assert.docEq(
- [{"time": ISODate("2024-01-01T00:00:00Z"), "tag": {"field": "A"}, "_id": 0, "a": "a"}],
- result);
})();
})();
diff --git a/jstests/core/timeseries/timeseries_project_pushdown.js b/jstests/core/timeseries/timeseries_project_pushdown.js
deleted file mode 100644
index 91b009aa00d..00000000000
--- a/jstests/core/timeseries/timeseries_project_pushdown.js
+++ /dev/null
@@ -1,196 +0,0 @@
-/**
- * Test the behavior of $project with pipelines that require the whole document. Specifically, we
- * are targeting that rewrites for $project with $getField, or '$$ROOT'/'$$CURRENT' should only
- * occur in certain situations.
- *
- * @tags: [
- * requires_timeseries,
- * does_not_support_stepdowns,
- * does_not_support_transactions,
- * ]
- */
-(function() {
-"use strict";
-
-const timeField = "t";
-const metaField = "meta1";
-const coll = db.timeseries_project_pushdown;
-
-function runTest({docs, pipeline, expectedResults}) {
- coll.drop();
- assert.commandWorked(db.createCollection(
- coll.getName(), {timeseries: {timeField: timeField, metaField: metaField}}));
- assert.commandWorked(coll.insertMany(docs));
- const results = coll.aggregate(pipeline).toArray();
- assert.sameMembers(expectedResults, results, () => {
- return `Pipeline: ${tojson(pipeline)}. Explain: ${
- tojson(coll.explain().aggregate(pipeline))}`;
- });
-}
-
-//
-// The following tests confirm the behavior of queries in the form: {$getField: "fieldName"}.
-//
-(function testMeta_OnlyStringField() {
- runTest({
- docs: [{_id: 1, [timeField]: new Date(), [metaField]: 2}],
- pipeline: [{$project: {new: {$getField: metaField}, _id: 0}}],
- expectedResults: [{new: 2}]
- });
-})();
-
-// $getField does not traverse objects, and should not be rewritten when it relies on a mix of
-// metaField and measurement fields. Let's validate that behavior.
-(function testDottedPath_OnlyStringField() {
- runTest({
- docs: [
- {_id: 1, [timeField]: new Date(), [metaField]: 2, "a.b": 3, a: {b: 2}},
- {_id: 2, [timeField]: new Date(), [metaField]: 2, a: {b: 2}} // missing field.
- ],
- pipeline: [{$project: {new: {$add: [`$${metaField}`, {$getField: "a.b"}]}}}],
- expectedResults: [{_id: 1, new: 5}, {_id: 2, new: null}]
- });
-})();
-
-//
-// The following tests confirm the behavior of queries in the form: {$getField: {$literal:
-// "fieldName"}}.
-//
-(function testDottedPath_LiteralExpr() {
- runTest({
- docs: [
- {_id: 1, [timeField]: new Date(), [metaField]: 2, "a.$b": 3, a: {b: 4}},
- {_id: 2, [timeField]: new Date(), [metaField]: 2, a: {b: 2}} // missing field.
- ],
- pipeline: [{$project: {new: {$add: [`$${metaField}`, {$getField: {$literal: "a.$b"}}]}}}],
- expectedResults: [{_id: 1, new: 5}, {_id: 2, new: null}]
- });
-}());
-
-// There is a difference between the metaField "meta1", and "$meta1". Field paths are allowed to
-// have a '$' and are accessed by $getField. We need to validate we return the correct results when
-// we have both the metaField and "$meta1".
-(function testDollarMeta_LiteralExpr() {
- runTest({
- docs: [
- {_id: 1, [timeField]: new Date(), [metaField]: 2},
- {_id: 2, [timeField]: new Date(), [metaField]: 2, "$meta1": 3} // missing field.
- ],
- pipeline: [{$project: {new: {$add: [`$${metaField}`, {$getField: {$literal: "$meta1"}}]}}}],
- expectedResults: [{_id: 1, new: null}, {_id: 2, new: 5}]
- });
-})();
-
-// The following tests confirm the behavior of queries in the form: {$getField: {input: "string",
-// field: "string"}}.
-//
-(function testMetaField_FieldAndInputString() {
- runTest({
- docs: [
- {_id: 1, [timeField]: new Date(), [metaField]: {b: 4}},
- {_id: 2, [timeField]: new Date(), [metaField]: {c: 5}} // missing subfield.
- ],
- pipeline: [{$project: {new: {$getField: {input: `$${metaField}`, field: "b"}}}}],
- expectedResults: [{_id: 1, new: 4}, {_id: 2}]
- });
-})();
-
-// Validate the correct results are returned when there is a field with '$' inside the metaField.
-// The rewrite should be valid and return the correct field.
-(function testMetaFieldObj_FieldAndInputString() {
- runTest({
- docs: [
- {_id: 1, [timeField]: new Date(), [metaField]: {"a.$b": 4}},
- {_id: 2, [timeField]: new Date(), [metaField]: {c: 5}} // missing subfield.
- ],
- pipeline: [{$project: {new: {$getField: {input: `$${metaField}`, field: "a.$b"}}}}],
- expectedResults: [{_id: 1, new: 4}, {_id: 2}]
- });
-})();
-
-// When we rely on both the metaField and a measurementField we should not perform the rewrite and
-// return the correct result.
-(function testDollarMeta_FieldAndInputString() {
- runTest({
- docs: [
- {_id: 1, [timeField]: new Date(), [metaField]: 2, a: {"$meta1": 4}},
- {_id: 2, [timeField]: new Date(), [metaField]: 2, a: {c: 5}} // missing subfield.
- ],
-
- pipeline: [{
- $project: {
- new: {
- $add: [`$${metaField}`, {$getField: {input: "$a", field: {$literal: "$meta1"}}}]
- }
- }
- }],
- expectedResults: [{_id: 1, new: 6}, {_id: 2, new: null}]
- });
-})();
-
-// same test as above but with $addFields and not $project.
-(function testDollarMeta_FieldAndInputString_AddFields() {
- const time = new Date();
- runTest({
- docs: [
- {_id: 1, [timeField]: time, [metaField]: 2, a: {"$meta1": 4}},
- {_id: 2, [timeField]: time, [metaField]: 2, a: {c: 5}} // missing subfield.
- ],
- pipeline: [{
- $addFields: {
- new: {
- $add: [`$${metaField}`, {$getField: {input: "$a", field: {$literal: "$meta1"}}}]
- }
- }
- }],
- expectedResults: [
- {[timeField]: time, [metaField]: 2, a: {"$meta1": 4}, _id: 1, new: 6},
- {[timeField]: time, [metaField]: 2, a: {c: 5}, _id: 2, new: null}
- ]
- });
-})();
-
-// This test validates that $project with '$$ROOT' which requires the whole document returns the
-// correct results.
-(function testProject_WithROOT() {
- const time = new Date();
- runTest({
- docs: [
- {_id: 1, [timeField]: time, [metaField]: 2, a: 2},
- {_id: 2, [timeField]: time, [metaField]: 2, b: 3}
- ],
- pipeline: [{$project: {new: "$$ROOT", _id: 1}}],
- expectedResults: [
- {_id: 1, new: {_id: 1, [timeField]: time, [metaField]: 2, a: 2}},
- {_id: 2, new: {_id: 2, [timeField]: time, [metaField]: 2, b: 3}}
- ]
- });
-})();
-
-(function testAddFields_WithROOT() {
- const time = new Date();
- runTest({
- docs: [
- {_id: 1, [timeField]: time, [metaField]: 2, a: 2},
- {_id: 2, [timeField]: time, [metaField]: 2, b: 3}
- ],
- pipeline: [{$addFields: {new: "$$ROOT"}}],
- expectedResults: [
- {
- _id: 1,
- [timeField]: time,
- [metaField]: 2,
- a: 2,
- new: {_id: 1, [timeField]: time, [metaField]: 2, a: 2}
- },
- {
- _id: 2,
- [timeField]: time,
- [metaField]: 2,
- b: 3,
- new: {_id: 2, [timeField]: time, [metaField]: 2, b: 3}
- }
- ]
- });
-})();
-})();
diff --git a/jstests/core/timeseries/timeseries_resume_after.js b/jstests/core/timeseries/timeseries_resume_after.js
index 66d020d43b4..a2b31972c85 100644
--- a/jstests/core/timeseries/timeseries_resume_after.js
+++ b/jstests/core/timeseries/timeseries_resume_after.js
@@ -8,7 +8,6 @@
* does_not_support_stepdowns,
* does_not_support_transactions,
* requires_getmore,
- * requires_fcv_60
* ]
*/
(function() {
@@ -92,25 +91,5 @@ TimeseriesTest.run((insert) => {
resumeToken = res.cursor.postBatchResumeToken;
jsTestLog("Got resume token " + tojson(resumeToken));
-
- // Test that '$_resumeAfter' fails if the recordId is Long.
- assert.commandFailedWithCode(db.runCommand({
- find: bucketsColl.getName(),
- filter: {},
- $_requestResumeToken: true,
- $_resumeAfter: {'$recordId': NumberLong(10)},
- hint: {$natural: 1}
- }),
- 7738600);
-
- // Test that '$_resumeAfter' fails if querying the time-series view.
- assert.commandFailedWithCode(db.runCommand({
- find: coll.getName(),
- filter: {},
- $_requestResumeToken: true,
- $_resumeAfter: {'$recordId': BinData(5, '1234')},
- hint: {$natural: 1}
- }),
- ErrorCodes.InvalidPipelineOperator);
});
})();
diff --git a/jstests/core/timeseries/timeseries_sparse_index.js b/jstests/core/timeseries/timeseries_sparse_index.js
index 7c9f7556e38..9ffd008ff62 100644
--- a/jstests/core/timeseries/timeseries_sparse_index.js
+++ b/jstests/core/timeseries/timeseries_sparse_index.js
@@ -13,9 +13,8 @@
"use strict";
load("jstests/core/timeseries/libs/timeseries.js");
-load("jstests/libs/feature_flag_util.js");
-if (!FeatureFlagUtil.isEnabled(db, "TimeseriesMetricIndexes")) {
+if (!TimeseriesTest.timeseriesMetricIndexesEnabled(db.getMongo())) {
jsTestLog(
"Skipped test as the featureFlagTimeseriesMetricIndexes feature flag is not enabled.");
return;
diff --git a/jstests/core/timeseries/timeseries_streaming_group.js b/jstests/core/timeseries/timeseries_streaming_group.js
deleted file mode 100644
index 6d97eb51621..00000000000
--- a/jstests/core/timeseries/timeseries_streaming_group.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * Tests that the $group stage will be replaced with $_internalStreamingGroup when group id is
- * monotonic on time and documents are sorted on time.
- *
- * @tags: [
- * # Explain of a resolved view must be executed by mongos.
- * directly_against_shardsvrs_incompatible,
- * does_not_support_stepdowns,
- * does_not_support_transactions,
- * requires_fcv_60,
- * requires_timeseries,
- * ]
- */
-(function() {
-"use strict";
-
-load("jstests/libs/analyze_plan.js"); // For getAggPlanStages
-load("jstests/libs/fail_point_util.js"); // For configureFailPoint
-
-const ts = db.timeseries_streaming_group;
-ts.drop();
-
-const coll = db.timeseires_streaming_group_regular_collection;
-coll.drop();
-
-assert.commandWorked(
- db.createCollection(ts.getName(), {timeseries: {timeField: "time", metaField: "meta"}}));
-
-const numTimes = 100;
-const numSymbols = 10;
-const minPrice = 100;
-const maxPrice = 200;
-const minAmount = 1;
-const maxAmount = 20;
-
-Random.setRandomSeed(1);
-
-const randRange = function(min, max) {
- return min + Random.randInt(max - min);
-};
-
-const symbols = [];
-for (let i = 0; i < numSymbols; i++) {
- let randomName = "";
- const randomStrLen = 5;
- for (let j = 0; j < randomStrLen; j++) {
- randomName += String.fromCharCode("A".charCodeAt(0) + Random.randInt(26));
- }
- symbols.push(randomName);
-}
-
-const documents = [];
-const startTime = 1641027600000;
-for (let i = 0; i < numTimes; i++) {
- for (const symbol of symbols) {
- documents.push({
- time: new Date(startTime + i * 1000),
- price: randRange(minPrice, maxPrice),
- amount: randRange(minAmount, maxAmount),
- meta: {"symbol": symbol}
- });
- }
-}
-
-assert.commandWorked(ts.insert(documents));
-assert.commandWorked(coll.insert(documents));
-
-// Incorrect use of $_internalStreamingGroup should return error
-assert.commandFailedWithCode(db.runCommand({
- aggregate: "timeseires_streaming_group_regular_collection",
- pipeline: [{
- $_internalStreamingGroup: {
- _id: {symbol: "$symbol", time: "$time"},
- count: {$sum: 1},
- $monotonicIdFields: ["price"]
- }
- }],
- cursor: {},
-}),
- 7026705);
-assert.commandFailedWithCode(db.runCommand({
- aggregate: "timeseires_streaming_group_regular_collection",
- pipeline: [{$_internalStreamingGroup: {_id: null, count: {$sum: 1}}}],
- cursor: {},
-}),
- 7026702);
-assert.commandFailedWithCode(db.runCommand({
- aggregate: "timeseires_streaming_group_regular_collection",
- pipeline:
- [{$_internalStreamingGroup: {_id: null, count: {$sum: 1}, $monotonicIdFields: ["_id"]}}],
- cursor: {},
-}),
- 7026708);
-
-const runTest = function(pipeline, expectedMonotonicIdFields) {
- const explain = assert.commandWorked(ts.explain().aggregate(pipeline));
- const streamingGroupStage = getAggPlanStage(explain, "$_internalStreamingGroup");
- assert.neq(streamingGroupStage, null);
- assert.eq(streamingGroupStage.$_internalStreamingGroup.$monotonicIdFields,
- expectedMonotonicIdFields);
-
- const found = ts.aggregate(pipeline).toArray();
- const expected = coll.aggregate(pipeline).toArray();
- assert.eq(expected, found);
-};
-
-runTest(
- [
- {$sort: {time: 1}},
- {
- $group: {
- _id: {
- symbol: "$meta.symbol",
- minute: {
- $subtract: [
- {$dateTrunc: {date: "$time", unit: "minute"}},
- {$dateTrunc: {date: new Date(startTime), unit: "minute"}},
- ]
- }
- },
- "average_price": {$avg: {$multiply: ["$price", "$amount"]}},
- "average_amount": {$avg: "$amount"}
- }
- },
- {$addFields: {"average_price": {$divide: ["$average_price", "$average_amount"]}}},
- {$sort: {_id: 1}}
- ],
- ["minute"]);
-
-runTest(
- [
- {$sort: {time: 1}},
- {
- $group: {
- _id: {$dateTrunc: {date: "$time", unit: "minute"}},
- "average_price": {$avg: {$multiply: ["$price", "$amount"]}},
- "average_amount": {$avg: "$amount"}
- }
- },
- {$addFields: {"average_price": {$divide: ["$average_price", "$average_amount"]}}},
- {$sort: {_id: 1}}
- ],
- ["_id"]);
-
-runTest(
- [
- {$sort: {time: 1}},
- {
- $group: {
- _id: "$time",
- "average_price": {$avg: {$multiply: ["$price", "$amount"]}},
- "average_amount": {$avg: "$amount"}
- }
- },
- {$addFields: {"average_price": {$divide: ["$average_price", "$average_amount"]}}},
- {$sort: {_id: 1}}
- ],
- ["_id"]);
-})();
diff --git a/jstests/core/timeseries/timeseries_union_with.js b/jstests/core/timeseries/timeseries_union_with.js
index e92e4c4ca37..b78bbd6937c 100644
--- a/jstests/core/timeseries/timeseries_union_with.js
+++ b/jstests/core/timeseries/timeseries_union_with.js
@@ -4,11 +4,6 @@
* @tags: [
* does_not_support_transactions,
* requires_timeseries,
- * # This test depends on certain writes ending up in the same bucket. Stepdowns and tenant
- * # migrations may result in writes splitting between two primaries, and thus different buckets.
- * does_not_support_stepdowns,
- * tenant_migration_incompatible,
- * references_foreign_collection,
* ]
*/
(function() {
diff --git a/jstests/core/timeseries/timeseries_update_mixed_schema_bucket.js b/jstests/core/timeseries/timeseries_update_mixed_schema_bucket.js
deleted file mode 100644
index 0211daa29d8..00000000000
--- a/jstests/core/timeseries/timeseries_update_mixed_schema_bucket.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Tests directly updating a time-series bucket to contain mixed schema.
- *
- * @tags: [
- * # $listCatalog does not include the tenant prefix in its results.
- * command_not_supported_in_serverless,
- * requires_timeseries,
- * # $listCatalog not supported inside of a multi-document transaction
- * does_not_support_transactions,
- * # $listCatalog only exists since v6
- * multiversion_incompatible,
- * ]
- */
-(function() {
-"use strict";
-load("jstests/core/timeseries/libs/timeseries.js"); // For 'TimeseriesTest'.
-
-TestData.skipEnforceTimeseriesBucketsAreAlwaysCompressedOnValidate = true;
-
-const testDB = db.getSiblingDB(jsTestName());
-const collName = "ts";
-
-assert.commandWorkedOrFailedWithCode(testDB.runCommand({drop: collName}),
- ErrorCodes.NamespaceNotFound);
-assert.commandWorked(
- testDB.createCollection(collName, {timeseries: {timeField: "t", metaField: "m"}}));
-const coll = testDB[collName];
-const bucketsColl = testDB["system.buckets." + collName];
-
-const bucket = {
- _id: ObjectId("65a6eb806ffc9fa4280ecac4"),
- control: {
- version: NumberInt(1),
- min: {
- _id: ObjectId("65a6eba7e6d2e848e08c3750"),
- t: ISODate("2024-01-16T20:48:00Z"),
- a: 0,
- },
- max: {
- _id: ObjectId("65a6eba7e6d2e848e08c3751"),
- t: ISODate("2024-01-16T20:48:39.448Z"),
- a: 1,
- },
- },
- meta: 0,
- data: {
- _id: {
- 0: ObjectId("65a6eba7e6d2e848e08c3750"),
- 1: ObjectId("65a6eba7e6d2e848e08c3751"),
- },
- t: {
- 0: ISODate("2024-01-16T20:48:39.448Z"),
- 1: ISODate("2024-01-16T20:48:39.448Z"),
- },
- a: {
- 0: 0,
- 1: 1,
- },
- }
-};
-
-const update = function() {
- return bucketsColl.update({_id: bucket._id},
- {$set: {"control.min.a": 1, "control.max.a": "a", "data.a.0": "a"}});
-};
-
-assert.commandWorked(bucketsColl.insert(bucket));
-assert.commandFailedWithCode(update(), ErrorCodes.CannotInsertTimeseriesBucketsWithMixedSchema);
-assert.eq(TimeseriesTest.bucketsMayHaveMixedSchemaData(bucketsColl), false);
-assert.commandWorked(
- testDB.runCommand({collMod: collName, timeseriesBucketsMayHaveMixedSchemaData: true}));
-assert.eq(TimeseriesTest.bucketsMayHaveMixedSchemaData(bucketsColl), true);
-assert.commandWorked(update());
-assert.commandWorked(bucketsColl.deleteOne({_id: bucket._id}));
-assert.eq(TimeseriesTest.bucketsMayHaveMixedSchemaData(bucketsColl), true);
-assert.commandWorked(
- testDB.runCommand({collMod: collName, timeseriesBucketsMayHaveMixedSchemaData: false}));
-assert.eq(TimeseriesTest.bucketsMayHaveMixedSchemaData(bucketsColl), false);
-})();
diff --git a/jstests/core/transaction_too_large_for_cache.js b/jstests/core/transaction_too_large_for_cache.js
deleted file mode 100644
index 224c23eedaf..00000000000
--- a/jstests/core/transaction_too_large_for_cache.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Tests that an operation requiring more cache than available fails instead of retrying infinitely.
- *
- * @tags: [
- * does_not_support_config_fuzzer,
- * requires_fcv_60,
- * requires_persistence,
- * requires_non_retryable_writes,
- * requires_wiredtiger,
- * no_selinux
- * ]
- */
-
-(function() {
-load("jstests/libs/fixture_helpers.js"); // For FixtureHelpers.
-load("jstests/libs/storage_engine_utils.js");
-
-// TODO (SERVER-39362): remove once parallel suite respects tags properly.
-if (!storageEngineIsWiredTiger()) {
- jsTestLog("Skipping test because storage engine is not WiredTiger.");
- return;
-}
-
-const doc = {
- x: []
-};
-for (var j = 0; j < 334000; j++) {
- doc.x.push("" + Math.random() + Math.random());
-}
-
-const coll = db[jsTestName()];
-coll.drop();
-
-// Maximum amount of indexes is 64. _id is implicit, and sharded collections also have an index on
-// the shard key.
-assert.commandWorked(coll.createIndex({x: "text"}));
-for (let i = 0; i < 61; i++) {
- assert.commandWorked(coll.createIndex({x: 1, ["field" + i]: 1}));
-}
-
-// Retry the operation until we eventually hit the TransactionTooLargeForCache. Retry on
-// WriteConflict or TemporarilyUnavailable errors, as those are expected to be returned if the
-// threshold for TransactionTooLargeForCache is not reached, possibly due to concurrent operations.
-assert.soon(() => {
- let result;
- try {
- result = coll.insert(doc);
- assert.commandFailedWithCode(result, ErrorCodes.TransactionTooLargeForCache);
- return true;
- } catch (e) {
- assert.commandFailedWithCode(result,
- [ErrorCodes.WriteConflict, ErrorCodes.TemporarilyUnavailable]);
- return false;
- }
-}, "Expected operation to eventually fail with TransactionTooLargeForCache error.");
-}());
diff --git a/jstests/core/ttl_index_options.js b/jstests/core/ttl_index_options.js
index b136680edc4..47ae2709073 100644
--- a/jstests/core/ttl_index_options.js
+++ b/jstests/core/ttl_index_options.js
@@ -1,10 +1,7 @@
/**
* Ensures that the options passed in for TTL indexes are validated during index creation.
*
- * @tags: [
- * requires_fcv_60,
- * requires_ttl_index,
- * ]
+ * @tags: [requires_ttl_index]
*/
(function() {
'use strict';
@@ -19,10 +16,11 @@ assert.commandFailedWithCode(
assert.commandFailedWithCode(coll.createIndexes([{x: 1}], {expireAfterSeconds: 9999999999999999}),
ErrorCodes.CannotCreateIndex);
-// Ensure that we can provide a time that is larger than the current epoch time.
-let secondsSinceEpoch = Math.floor(Date.now() / 1000);
-assert.commandWorked(
- coll.createIndexes([{x_before_epoch: 1}], {expireAfterSeconds: secondsSinceEpoch + 1000}));
+// Ensure that we cannot provide a time that is larger than the current epoch time.
+let secondsSinceEpoch = Date.now() / 1000;
+assert.commandFailedWithCode(
+ coll.createIndexes([{x: 1}], {expireAfterSeconds: secondsSinceEpoch + 1000}),
+ ErrorCodes.CannotCreateIndex);
// 'expireAfterSeconds' cannot be less than 0.
assert.commandFailedWithCode(coll.createIndexes([{x: 1}], {expireAfterSeconds: -1}),
diff --git a/jstests/core/txns/abort_expired_transaction.js b/jstests/core/txns/abort_expired_transaction.js
index 54418596967..b211ef7b132 100644
--- a/jstests/core/txns/abort_expired_transaction.js
+++ b/jstests/core/txns/abort_expired_transaction.js
@@ -33,11 +33,6 @@ try {
const session = db.getMongo().startSession(sessionOptions);
const sessionDb = session.getDatabase(testDBName);
- // Number of passes made by the "abortExpiredTransactions" thread before the transaction
- // expires.
- const abortExpiredTransactionsPassesPreAbort =
- db.serverStatus().metrics.abortExpiredTransactions.passes;
-
let txnNumber = 0;
jsTest.log("Insert a document starting a transaction.");
@@ -69,14 +64,6 @@ try {
"currentOp reports that the idle transaction still exists, it has not been " +
"aborted as expected.");
- assert.soon(() => {
- // For this expired transaction to abort, the "abortExpiredTransactions" thread has to
- // perform at least one pass.
- const serverStatus = db.serverStatus();
- return abortExpiredTransactionsPassesPreAbort <
- serverStatus.metrics.abortExpiredTransactions.passes;
- });
-
jsTest.log(
"Attempt to do a write in the transaction, which should fail because the transaction " +
"was aborted");
diff --git a/jstests/core/txns/aggregation_in_transaction.js b/jstests/core/txns/aggregation_in_transaction.js
index 40d7030fe1f..ec1c62133bb 100644
--- a/jstests/core/txns/aggregation_in_transaction.js
+++ b/jstests/core/txns/aggregation_in_transaction.js
@@ -1,5 +1,5 @@
// Tests that aggregation is supported in transactions.
-// @tags: [uses_transactions, uses_snapshot_read_concern, references_foreign_collection]
+// @tags: [uses_transactions, uses_snapshot_read_concern]
(function() {
"use strict";
diff --git a/jstests/core/txns/out_not_blocked_by_txn.js b/jstests/core/txns/out_not_blocked_by_txn.js
deleted file mode 100644
index a48097c9eab..00000000000
--- a/jstests/core/txns/out_not_blocked_by_txn.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Test that renaming a collection through $out takes database IX lock and will not be blocked by
- * transactions. This test is created to ensure that the scenario occuring in the case linked in
- * SERVER-72703, where a compact operation (which took an IX DB lock) blocked a rename with $out,
- * which required an exclusive DB lock. Now that $out should take an IX DB lock, renaming with
- * $out should not be blocked by operations taking an IX lock. Renaming with $out across
- * different databases still takes an X lock.
- *
- * @tags: [uses_transactions, requires_db_locking, assumes_unsharded_collection]
- */
-let dbName = jsTestName();
-let mydb = db.getSiblingDB(dbName);
-
-// Drop the collections that we will be using in this test, both for the transaction and for the
-// rename operation, and wait for majority confirmation.
-mydb.txn.drop({writeConcern: {w: "majority"}});
-mydb.a.drop({writeConcern: {w: "majority"}});
-mydb.b.drop({writeConcern: {w: "majority"}});
-mydb.c.drop({writeConcern: {w: "majority"}});
-
-// Populate our collections.
-assert.commandWorked(mydb.txn.insert({x: 1}));
-assert.commandWorked(mydb.a.insert([{x: 1}]));
-assert.commandWorked(mydb.c.insert({x: 1}));
-
-// Begin a session for our transaction.
-const session = mydb.getMongo().startSession();
-const sessionDb = session.getDatabase(dbName);
-
-session.startTransaction();
-// This holds a database IX lock and a collection IX lock on "test.txn".
-sessionDb.t.insert({y: 1});
-
-// $out should now also only require an IX lock.
-// Test the scenario where we rename collection 'a' to collection 'b', which doesn't exist.
-assert.commandWorked(
- mydb.runCommand({aggregate: "a", pipeline: [{$out: {db: dbName, coll: "b"}}], cursor: {}}));
-// Now test the scenario where we rename collection 'b' to collection 'c', which does exist.
-// This should drop collection 'c'.
-assert.commandWorked(
- mydb.runCommand({aggregate: "b", pipeline: [{$out: {db: dbName, coll: "c"}}], cursor: {}}));
-
-// Now commit the transaction.
-assert.commandWorked(session.commitTransaction_forTesting());
diff --git a/jstests/core/txns/prepare_conflict_aggregation_behavior.js b/jstests/core/txns/prepare_conflict_aggregation_behavior.js
index c07f96e2b54..c62b7370dc6 100644
--- a/jstests/core/txns/prepare_conflict_aggregation_behavior.js
+++ b/jstests/core/txns/prepare_conflict_aggregation_behavior.js
@@ -3,12 +3,7 @@
* should not block on prepare conflicts, but writing out to a collection as a part of an aggregate
* pipeline should block on prepare conflicts.
*
- * The test runs commands that are not allowed with security token: endSession, prepareTransaction.
- * @tags: [
- * references_foreign_collection,
- * uses_transactions,
- * uses_prepare_transaction,
- * ]
+ * @tags: [uses_transactions, uses_prepare_transaction]
*/
(function() {
"use strict";
diff --git a/jstests/core/txns/transaction_too_large_for_cache.js b/jstests/core/txns/transaction_too_large_for_cache.js
deleted file mode 100644
index 47171a0ee73..00000000000
--- a/jstests/core/txns/transaction_too_large_for_cache.js
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- * Tests a multi-document transaction requiring more cache than available fails with the expected
- * error code instead of a generic WriteConflictException.
- *
- * @tags: [
- * does_not_support_config_fuzzer,
- * requires_fcv_60,
- * requires_persistence,
- * requires_non_retryable_writes,
- * requires_wiredtiger,
- * uses_transactions,
- * ]
- */
-
-(function() {
-load("jstests/libs/fixture_helpers.js"); // For FixtureHelpers.
-load('jstests/libs/transactions_util.js');
-
-function getWtCacheSizeBytes() {
- let serverStatus;
- if (FixtureHelpers.isReplSet(db) || FixtureHelpers.isMongos(db)) {
- serverStatus = FixtureHelpers.getPrimaries(db)[0].getDB('admin').serverStatus();
- } else {
- serverStatus = db.serverStatus();
- }
-
- assert.commandWorked(serverStatus);
- return serverStatus.wiredTiger.cache["maximum bytes configured"];
-}
-
-const doc1 = {
- x: []
-};
-for (var j = 0; j < 100000; j++) {
- doc1.x.push("" + Math.random() + Math.random());
-}
-
-const session = db.getMongo().startSession();
-const sessionDb = session.getDatabase(db.getName());
-const coll = sessionDb[jsTestName()];
-coll.drop();
-
-// Scale the load in proportion to WT cache size, to reduce test run time.
-// A single collection can only have up to 64 indexes. Cap at _id + 1 text index + 62 indexes.
-const nIndexes = Math.min(Math.ceil(getWtCacheSizeBytes() * 2 / (1024 * 1024 * 1024)), 62);
-assert.commandWorked(coll.createIndex({x: "text"}));
-for (let i = 0; i < nIndexes; i++) {
- assert.commandWorked(coll.createIndex({x: 1, ["field" + i]: 1}));
-}
-
-// Retry the transaction until we eventually hit the TransactionTooLargeForCache. Only retry on
-// WriteConflict error, which is the only expected error besides TransactionTooLargeForCache.
-assert.soon(() => {
- session.startTransaction();
-
- // Keep inserting documents in the transaction until we eventually hit the cache limit.
- let insertCount = 0;
- let result;
- try {
- while (true) {
- try {
- ++insertCount;
- result = coll.insert(doc1);
- assert.commandWorked(result);
- } catch (e) {
- session.abortTransaction();
- assert.commandFailedWithCode(result, ErrorCodes.TransactionTooLargeForCache);
- break;
- }
- }
- } catch (e) {
- assert.commandFailedWithCode(result, ErrorCodes.WriteConflict);
- return false;
- }
-
- // The error should not have a transient transaction error label. At this point the error must
- // have been TransactionTooLargeForCache. We do this check here to avoid having to check
- // exception types in the outermost catch, in case this assertion fires.
- assert(!TransactionsUtil.isTransientTransactionError(result), result);
-
- jsTestLog("Iterations until TransactionTooLargeForCache occured: " + insertCount);
-
- return true;
-}, "Expected a transaction to eventually fail with TransactionTooLargeForCache error.");
-}());
diff --git a/jstests/core/views/invalid_system_views.js b/jstests/core/views/invalid_system_views.js
index 15b4ab6bc3b..25e973ed9a1 100644
--- a/jstests/core/views/invalid_system_views.js
+++ b/jstests/core/views/invalid_system_views.js
@@ -13,8 +13,6 @@
* requires_replication,
* # The drop of offending views may not happen on the donor after a committed migration.
* tenant_migration_incompatible,
- * uses_compact,
- * references_foreign_collection,
* ]
*/
diff --git a/jstests/core/views/views_aggregation.js b/jstests/core/views/views_aggregation.js
index 287bc5af667..537ec3ee008 100644
--- a/jstests/core/views/views_aggregation.js
+++ b/jstests/core/views/views_aggregation.js
@@ -9,7 +9,6 @@
* requires_non_retryable_commands,
* # Explain of a resolved view must be executed by mongos.
* directly_against_shardsvrs_incompatible,
- * references_foreign_collection,
* ]
*/
(function() {
diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js
index 7884b8fb6b2..45f19278511 100644
--- a/jstests/core/views/views_all_commands.js
+++ b/jstests/core/views/views_all_commands.js
@@ -12,7 +12,6 @@
// tenant_migration_incompatible,
// # Explain of a resolved view must be executed by mongos.
// directly_against_shardsvrs_incompatible,
-// uses_compact
// ]
/*
@@ -127,7 +126,6 @@ let viewsCommandTests = {
_configsvrShardCollection:
{skip: isAnInternalCommand}, // TODO SERVER-58843: Remove once 6.0 becomes last LTS
_configsvrUpdateZoneKeyRange: {skip: isAnInternalCommand},
- _dropConnectionsToMongot: {skip: isAnInternalCommand},
_flushDatabaseCacheUpdates: {skip: isUnrelated},
_flushDatabaseCacheUpdatesWithWriteConcern: {skip: isUnrelated},
_flushReshardingStateChange: {skip: isUnrelated},
@@ -141,7 +139,6 @@ let viewsCommandTests = {
_killOperations: {skip: isUnrelated},
_mergeAuthzCollections: {skip: isAnInternalCommand},
_migrateClone: {skip: isAnInternalCommand},
- _mongotConnPoolStats: {skip: isAnInternalCommand},
_movePrimary: {skip: isAnInternalCommand},
_recvChunkAbort: {skip: isAnInternalCommand},
_recvChunkCommit: {skip: isAnInternalCommand},
@@ -283,7 +280,6 @@ let viewsCommandTests = {
assert.commandWorked(conn.runCommand({dropAllRolesFromDatabase: 1}));
}
},
- createSearchIndexes: {skip: isUnrelated},
createUser: {
command: {createUser: "testuser", pwd: "testpass", roles: []},
setup: function(conn) {
@@ -349,7 +345,6 @@ let viewsCommandTests = {
assert.commandWorked(conn.runCommand({dropAllRolesFromDatabase: 1}));
}
},
- dropSearchIndex: {skip: isUnrelated},
dropUser: {skip: isUnrelated},
echo: {skip: isUnrelated},
emptycapped: {
@@ -376,6 +371,7 @@ let viewsCommandTests = {
getCmdLineOpts: {skip: isUnrelated},
getDefaultRWConcern: {skip: isUnrelated},
getDiagnosticData: {skip: isUnrelated},
+ getFreeMonitoringStatus: {skip: isUnrelated},
getLastError: {skip: isUnrelated},
getLog: {skip: isUnrelated},
getMore: {
@@ -478,7 +474,6 @@ let viewsCommandTests = {
listCommands: {skip: isUnrelated},
listDatabases: {skip: isUnrelated},
listIndexes: {command: {listIndexes: "view"}, expectFailure: true},
- listSearchIndexes: {skip: isUnrelated},
listShards: {skip: isUnrelated},
lockInfo: {skip: isUnrelated},
logApplicationMessage: {skip: isUnrelated},
@@ -546,6 +541,7 @@ let viewsCommandTests = {
skipSharded: true,
}
],
+ repairDatabase: {skip: isUnrelated},
repairShardedCollectionChunksHistory: {
command: {repairShardedCollectionChunksHistory: "test.view"},
skipStandalone: true,
@@ -609,7 +605,6 @@ let viewsCommandTests = {
rotateCertificates: {skip: isUnrelated},
saslContinue: {skip: isUnrelated},
saslStart: {skip: isUnrelated},
- sbe: {skip: isAnInternalCommand},
serverStatus: {command: {serverStatus: 1}, skip: isUnrelated},
setChangeStreamOptions: {skip: isUnrelated}, // TODO SERVER-65353 remove in 6.1.
setIndexCommitQuorum: {skip: isUnrelated},
@@ -617,7 +612,7 @@ let viewsCommandTests = {
setCommittedSnapshot: {skip: isAnInternalCommand},
setDefaultRWConcern: {skip: isUnrelated},
setFeatureCompatibilityVersion: {skip: isUnrelated},
- setProfilingFilterGlobally: {skip: isUnrelated},
+ setFreeMonitoring: {skip: isUnrelated},
setParameter: {skip: isUnrelated},
setShardVersion: {skip: isUnrelated},
setClusterParameter: {skip: isUnrelated},
@@ -690,7 +685,6 @@ let viewsCommandTests = {
assert.commandWorked(conn.runCommand({dropAllRolesFromDatabase: 1}));
}
},
- updateSearchIndex: {skip: isUnrelated},
updateUser: {skip: isUnrelated},
updateZoneKeyRange: {skip: isUnrelated},
usersInfo: {skip: isUnrelated},
diff --git a/jstests/core/views/views_collation.js b/jstests/core/views/views_collation.js
index 65deb11edbc..169e9309740 100644
--- a/jstests/core/views/views_collation.js
+++ b/jstests/core/views/views_collation.js
@@ -6,7 +6,6 @@
// requires_non_retryable_commands,
// # Explain of a resolved view must be executed by mongos.
// directly_against_shardsvrs_incompatible,
-// references_foreign_collection,
// ]
/**
diff --git a/jstests/core/views/views_creation.js b/jstests/core/views/views_creation.js
index c24a008342d..9528199996a 100644
--- a/jstests/core/views/views_creation.js
+++ b/jstests/core/views/views_creation.js
@@ -11,7 +11,6 @@
* requires_non_retryable_commands,
* # Tenant migrations don't support applyOps.
* tenant_migration_incompatible,
- * references_foreign_collection,
* ]
*/
(function() {
diff --git a/jstests/core/views/views_validation.js b/jstests/core/views/views_validation.js
index 4dea7c9491b..02c060fd50a 100644
--- a/jstests/core/views/views_validation.js
+++ b/jstests/core/views/views_validation.js
@@ -2,7 +2,6 @@
// # Running getCollection on views in sharded suites tries to shard views, which fails.
// assumes_unsharded_collection,
// requires_non_retryable_commands,
-// references_foreign_collection,
// ]
(function() {
diff --git a/jstests/core/wildcard_index_validindex.js b/jstests/core/wildcard_index_validindex.js
index c4a2ea9c2ac..24ecdcf77cf 100644
--- a/jstests/core/wildcard_index_validindex.js
+++ b/jstests/core/wildcard_index_validindex.js
@@ -98,18 +98,6 @@ assert.commandFailedWithCode(coll.createIndex({"$**": "wildcard"}), ErrorCodes.C
// Cannot create a compound wildcard index.
assert.commandFailedWithCode(coll.createIndex({"$**": 1, "a": 1}), ErrorCodes.CannotCreateIndex);
assert.commandFailedWithCode(coll.createIndex({"a": 1, "$**": 1}), ErrorCodes.CannotCreateIndex);
-assert.commandFailedWithCode(coll.createIndex({"obj.$**": 1, "a": 1}),
- ErrorCodes.CannotCreateIndex);
-assert.commandFailedWithCode(db.runCommand({
- createIndexes: kCollectionName,
- indexes: [{wildcardProjection: {a: 1, c: 1, d: 1}, key: {"$**": 1, b: 1}}]
-}),
- ErrorCodes.CannotCreateIndex);
-assert.commandFailedWithCode(db.runCommand({
- createIndexes: kCollectionName,
- indexes: [{key: {"$**": 1, b: 1}, wildcardProjection: {a: 1, c: 1, d: 1}}]
-}),
- ErrorCodes.CannotCreateIndex);
// Cannot create an wildcard index with an invalid spec.
assert.commandFailedWithCode(coll.createIndex({"a.$**.$**": 1}), ErrorCodes.CannotCreateIndex);
@@ -153,9 +141,4 @@ assert.commandFailedWithCode(
assert.commandFailedWithCode(
createIndexHelper({"a.$**": 1}, {name: kIndexName, wildcardProjection: {b: 0}}),
ErrorCodes.FailedToParse);
-assert.commandFailedWithCode(db.runCommand({
- createIndexes: kCollectionName,
- indexes: [{wildcardProjection: {b: 1}, key: {"a.$**": 1}}]
-}),
- ErrorCodes.FailedToParse);
})();