summaryrefslogtreecommitdiff
path: root/jstests/aggregation
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/aggregation')
-rw-r--r--jstests/aggregation/sources/addFields/use_cases.js64
-rw-r--r--jstests/aggregation/sources/addFields/weather.js101
2 files changed, 165 insertions, 0 deletions
diff --git a/jstests/aggregation/sources/addFields/use_cases.js b/jstests/aggregation/sources/addFields/use_cases.js
new file mode 100644
index 00000000000..725408fb40d
--- /dev/null
+++ b/jstests/aggregation/sources/addFields/use_cases.js
@@ -0,0 +1,64 @@
+/**
+ * $addFields can be used to add fixed and computed fields to documents while preserving the
+ * original document. Verify that using $addFields and adding computed fields in a $project yield
+ * the same result.
+ */
+
+(function() {
+ "use strict";
+
+ // For arrayEq.
+ load("jstests/aggregation/extras/utils.js");
+
+ const dbName = "test";
+ const collName = jsTest.name();
+
+ function doExecutionTest(conn) {
+ const coll = conn.getDB(dbName).getCollection(collName);
+ coll.drop();
+
+ // Insert a bunch of documents of the form above.
+ const nDocs = 10;
+ for (let i = 0; i < nDocs; i++) {
+ assert.writeOK(coll.insert({"_id": i, "2i": i * 2, "3i": i * 3}));
+ }
+
+ // Add the minimum, maximum, and average temperatures, and make sure that doing the same
+ // with addFields yields the correct answer.
+ // First compute with $project, since we know all the fields in this document.
+ let projectPipe = [{
+ $project: {
+ "2i": 1,
+ "3i": 1,
+ "6i^2": {"$multiply": ["$2i", "$3i"]},
+ // _id is implicitly included.
+ }
+ }];
+ let correct = coll.aggregate(projectPipe).toArray();
+
+ // Then compute the same results using $addFields.
+ let addFieldsPipe = [{
+ $addFields: {
+ "6i^2": {"$multiply": ["$2i", "$3i"]},
+ // All other fields are implicitly included.
+ }
+ }];
+ let addFieldsResult = coll.aggregate(addFieldsPipe).toArray();
+
+ // Then assert they are the same.
+ assert(arrayEq(addFieldsResult, correct),
+ "$addFields does not work the same as a $project with computed and included fields");
+ }
+
+ // Test against the standalone started by resmoke.py.
+ let conn = db.getMongo();
+ doExecutionTest(conn);
+ print("Success! Standalone execution use case test for $addFields passed.");
+
+ // Test against a sharded cluster.
+ let st = new ShardingTest({shards: 2});
+ doExecutionTest(st.s0);
+ st.stop();
+ print("Success! Sharding use case test for $addFields passed.");
+
+}()); \ No newline at end of file
diff --git a/jstests/aggregation/sources/addFields/weather.js b/jstests/aggregation/sources/addFields/weather.js
new file mode 100644
index 00000000000..7e2be837329
--- /dev/null
+++ b/jstests/aggregation/sources/addFields/weather.js
@@ -0,0 +1,101 @@
+/**
+ * $addFields can be used to add fixed and computed fields to documents while preserving the
+ * original document. Verify that using $addFields and adding computed fields in a $project yield
+ * the same result. Use the sample case of computing weather metadata.
+ */
+
+(function() {
+ "use strict";
+
+ // For arrayEq.
+ load("jstests/aggregation/extras/utils.js");
+
+ const dbName = "test";
+ const collName = jsTest.name();
+
+ Random.setRandomSeed();
+
+ /**
+ * Helper to generate an array of specified length of numbers in the specified range.
+ */
+ function randomArray(length, minValue, maxValue) {
+ let array = [];
+ for (let i = 0; i < length; i++) {
+ array.push((Random.rand() * (maxValue - minValue)) + minValue);
+ }
+ return array;
+ }
+
+ /**
+ * Helper to generate a randomized document with the following schema:
+ * {
+ * month: <integer month of year>,
+ * day: <integer day of month>,
+ * temperatures: <array of 24 decimal temperatures>
+ * }
+ */
+ function generateRandomDocument() {
+ const minTemp = -40;
+ const maxTemp = 120;
+
+ return {
+ month: Random.randInt(12) + 1, // 1-12
+ day: Random.randInt(31) + 1, // 1-31
+ temperatures: randomArray(24, minTemp, maxTemp),
+ };
+ }
+
+ function doExecutionTest(conn) {
+ const coll = conn.getDB(dbName).getCollection(collName);
+ coll.drop();
+
+ // Insert a bunch of documents of the form above.
+ const nDocs = 10;
+ for (let i = 0; i < nDocs; i++) {
+ assert.writeOK(coll.insert(generateRandomDocument()));
+ }
+
+ // Add the minimum, maximum, and average temperatures, and make sure that doing the same
+ // with addFields yields the correct answer.
+ // First compute with $project, since we know all the fields in this document.
+ let projectWeatherPipe = [{
+ $project: {
+ "month": 1,
+ "day": 1,
+ "temperatures": 1,
+ "minTemp": {"$min": "$temperatures"},
+ "maxTemp": {"$max": "$temperatures"},
+ "average": {"$avg": "$temperatures"},
+ // _id is implicitly included.
+ }
+ }];
+ let correctWeather = coll.aggregate(projectWeatherPipe).toArray();
+
+ // Then compute the same results using $addFields.
+ let addFieldsWeatherPipe = [{
+ $addFields: {
+ "minTemp": {"$min": "$temperatures"},
+ "maxTemp": {"$max": "$temperatures"},
+ "average": {"$avg": "$temperatures"},
+ // All other fields are implicitly included.
+ }
+ }];
+ let addFieldsResult = coll.aggregate(addFieldsWeatherPipe).toArray();
+
+ // Then assert they are the same.
+ assert(arrayEq(addFieldsResult, correctWeather),
+ "$addFields does not work the same as a $project with computed and included fields");
+ }
+
+ // Test against the standalone started by resmoke.py.
+ let conn = db.getMongo();
+ doExecutionTest(conn);
+ print("Success! Standalone execution weather test for $addFields passed.");
+
+ // Test against a sharded cluster.
+ let st = new ShardingTest({shards: 2});
+ doExecutionTest(st.s0);
+ st.stop();
+ print("Success! Sharding weather test for $addFields passed.");
+
+}()); \ No newline at end of file