/** * Tests that query options are not dropped by mongos when a query against a view is rewritten as an * aggregation against the underlying collection. */ (function() { "use strict"; load("jstests/libs/profiler.js"); // For profilerHasSingleMatchingEntryOrThrow. const st = new ShardingTest({ name: "view_rewrite", shards: 2, other: { rs0: { nodes: [ {rsConfig: {priority: 1}}, {rsConfig: {priority: 0, tags: {"tag": "secondary"}}} ] }, rs1: { nodes: [ {rsConfig: {priority: 1}}, {rsConfig: {priority: 0, tags: {"tag": "secondary"}}} ] }, enableBalancer: false } }); const mongos = st.s; const config = mongos.getDB("config"); const mongosDB = mongos.getDB("view_rewrite"); assert.commandWorked(mongosDB.dropDatabase()); const coll = mongosDB.getCollection("coll"); assert.commandWorked(config.adminCommand({enableSharding: mongosDB.getName()})); st.ensurePrimaryShard(mongosDB.getName(), "view_rewrite-rs0"); const rs0Secondary = st.rs0.getSecondary(); const rs1Primary = st.rs1.getPrimary(); const rs1Secondary = st.rs1.getSecondary(); for (let i = 0; i < 10; ++i) { assert.writeOK(coll.insert({a: i})); } assert.commandWorked(mongosDB.createView("view", coll.getName(), [])); const view = mongosDB.getCollection("view"); // // Confirms that queries run against views on mongos result in execution of a rewritten // aggregation that contains all expected query options. // function confirmOptionsInProfiler(shardPrimary) { assert.commandWorked(shardPrimary.setProfilingLevel(2)); // Aggregation assert.commandWorked(mongosDB.runCommand({ aggregate: "view", pipeline: [], comment: "agg_rewrite", maxTimeMS: 5 * 60 * 1000, readConcern: {level: "linearizable"}, cursor: {} })); profilerHasSingleMatchingEntryOrThrow({ profileDB: shardPrimary, filter: { "ns": coll.getFullName(), "command.aggregate": coll.getName(), "command.comment": "agg_rewrite", "command.maxTimeMS": {"$exists": true}, "command.readConcern": {level: "linearizable"}, "command.pipeline.$mergeCursors": {"$exists": false}, "nreturned": {"$exists": true} } }); // Find assert.commandWorked(mongosDB.runCommand({ find: "view", comment: "find_rewrite", maxTimeMS: 5 * 60 * 1000, readConcern: {level: "linearizable"} })); profilerHasSingleMatchingEntryOrThrow({ profileDB: shardPrimary, filter: { "ns": coll.getFullName(), "command.aggregate": coll.getName(), "command.comment": "find_rewrite", "command.maxTimeMS": {"$exists": true}, "command.readConcern": {level: "linearizable"}, "command.pipeline.$mergeCursors": {"$exists": false}, "nreturned": {"$exists": true} } }); // Count assert.commandWorked(mongosDB.runCommand({ count: "view", comment: "count_rewrite", maxTimeMS: 5 * 60 * 1000, readConcern: {level: "linearizable"} })); profilerHasSingleMatchingEntryOrThrow({ profileDB: shardPrimary, filter: { "ns": coll.getFullName(), "command.aggregate": coll.getName(), "command.comment": "count_rewrite", "command.maxTimeMS": {"$exists": true}, "command.readConcern": {level: "linearizable"}, "command.pipeline.$mergeCursors": {"$exists": false}, "nreturned": {"$exists": true} } }); // Distinct assert.commandWorked(mongosDB.runCommand({ distinct: "view", key: "a", comment: "distinct_rewrite", maxTimeMS: 5 * 60 * 1000, readConcern: {level: "linearizable"} })); profilerHasSingleMatchingEntryOrThrow({ profileDB: shardPrimary, filter: { "ns": coll.getFullName(), "command.aggregate": coll.getName(), "command.comment": "distinct_rewrite", "command.maxTimeMS": {"$exists": true}, "command.readConcern": {level: "linearizable"}, "command.pipeline.$mergeCursors": {"$exists": false}, "nreturned": {"$exists": true} } }); assert.commandWorked(shardPrimary.setProfilingLevel(0)); shardPrimary.system.profile.drop(); } // // Confirms that queries run against views on mongos are executed against a tagged secondary, as // per readPreference setting. // function confirmReadPreference(shardSecondary) { assert.commandWorked(shardSecondary.setProfilingLevel(2)); // Aggregation assert.commandWorked(mongosDB.runCommand({ query: {aggregate: "view", pipeline: [], comment: "agg_readPref", cursor: {}}, $readPreference: {mode: "nearest", tags: [{tag: "secondary"}]} })); profilerHasSingleMatchingEntryOrThrow({ profileDB: shardSecondary, filter: { "ns": coll.getFullName(), "command.aggregate": coll.getName(), "command.comment": "agg_readPref", "command.pipeline.$mergeCursors": {"$exists": false}, "nreturned": {"$exists": true} } }); // Find assert.commandWorked(mongosDB.runCommand({ query: {find: "view", comment: "find_readPref", maxTimeMS: 5 * 60 * 1000}, $readPreference: {mode: "nearest", tags: [{tag: "secondary"}]} })); profilerHasSingleMatchingEntryOrThrow({ profileDB: shardSecondary, filter: { "ns": coll.getFullName(), "command.aggregate": coll.getName(), "command.comment": "find_readPref", "command.pipeline.$mergeCursors": {"$exists": false}, "nreturned": {"$exists": true} } }); // Count assert.commandWorked(mongosDB.runCommand({ query: {count: "view", comment: "count_readPref"}, $readPreference: {mode: "nearest", tags: [{tag: "secondary"}]} })); profilerHasSingleMatchingEntryOrThrow({ profileDB: shardSecondary, filter: { "ns": coll.getFullName(), "command.aggregate": coll.getName(), "command.comment": "count_readPref", "command.pipeline.$mergeCursors": {"$exists": false}, "nreturned": {"$exists": true} } }); // Distinct assert.commandWorked(mongosDB.runCommand({ query: {distinct: "view", key: "a", comment: "distinct_readPref"}, $readPreference: {mode: "nearest", tags: [{tag: "secondary"}]} })); profilerHasSingleMatchingEntryOrThrow({ profileDB: shardSecondary, filter: { "ns": coll.getFullName(), "command.aggregate": coll.getName(), "command.comment": "distinct_readPref", "command.pipeline.$mergeCursors": {"$exists": false}, "nreturned": {"$exists": true} } }); assert.commandWorked(shardSecondary.setProfilingLevel(0)); } // // Test rewrite for queries run against an unsharded collection. // confirmOptionsInProfiler(st.rs0.getPrimary().getDB(mongosDB.getName())); confirmReadPreference(st.rs0.getSecondary().getDB(mongosDB.getName())); // // Test rewrite for queries run against a sharded collection. // assert.commandWorked(coll.createIndex({a: 1})); assert.commandWorked(config.adminCommand({shardCollection: coll.getFullName(), key: {a: 1}})); assert.commandWorked(mongos.adminCommand({split: coll.getFullName(), middle: {a: 6}})); assert.commandWorked(mongosDB.adminCommand( {moveChunk: coll.getFullName(), find: {a: 25}, to: "view_rewrite-rs1"})); // Sharded tests are run against the non-primary shard for the "view_rewrite" db. confirmOptionsInProfiler(st.rs1.getPrimary().getDB(mongosDB.getName())); confirmReadPreference(st.rs1.getSecondary().getDB(mongosDB.getName())); st.stop(); })();