UNPKG

@irrelon/forerunnerdb-core

Version:

ForerunnerDB core utilities for operating on JSON data.

724 lines (646 loc) 18.4 kB
import assert from "assert"; import {update} from "./update"; import {$replaceValue} from "./operate.js"; describe("update", () => { describe("Modes of operation", () => { it("By query", async () => { const dataArr = [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "foo": false, "newVal": "bar" }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.strictEqual(dataArr[0].foo, false, "Correct value"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "foo": false, "newVal": "bar" }, { "_id": "2", "foo": true }], "Correct value"); }); it("By query with $in", async () => { const dataArr = [{ "_id": "1", "foo": true }, { "_id": "2", "foo": "true" }, { "_id": "3", "foo": false }, { "_id": "4", "foo": "false" }]; assert.strictEqual(dataArr.length, 4, "Number of documents is correct"); const updateResult = await update(dataArr, { "foo": { $in: [true, "true"] } }, { "foo": false, "newVal": "bar" }); assert.strictEqual(updateResult.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr.length, 4, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.strictEqual(dataArr[0].foo, false, "Correct value"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "foo": false, "newVal": "bar" }, { "_id": "2", "foo": false, "newVal": "bar" }, { "_id": "3", "foo": false }, { "_id": "4", "foo": "false" }], "Correct value"); }); it("By query with nested $in", async () => { const dataArr = [{ "_id": "1", arr: [{ "foo": true, arr: [{ "foo": "some value" }, { "foo": "some other value" }, { "foo": true }, { "foo": "true" }, { "foo": "some value" }, { "foo": "some other value" }] }, { "foo": "true" }, { "foo": false }, { "foo": "false" }] }]; assert.strictEqual(dataArr.length, 1, "Number of documents is correct"); // Where I left this was that this use case doesn't work yet. We don't have a way to track // the array indexes of each path that was modified in order to apply the update to the // correct sub-document. I'm also not sure about the update query structure and if it should // have an array index placeholder with a $ so that we know we should be filling in the // array index data there. I almost certainly think we should be. // As we match and iterate through an array, let's record the array indexes // that way, each array we encounter can have the index recorded so if we iterate // through two arrays the indexes might be recorded as [[0, 3], [1, 2]] then this can be // passed to the update operation and for each index list, we can fill the appropriate // index values where the dollars are and target the correct item in the object to // update. We need an array of array indexes because multiple sub-documents can match // a query so the update needs to be applied to each matching sub document const updateResult = await update(dataArr, { "arr.arr.foo": { $in: [true, "true"] } }, { "arr.$.arr.$.foo": false, "arr.$.arr.$.newVal": "bar" }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", arr: [{ "foo": true, arr: [{ "foo": "some value" }, { "foo": "some other value" }, { "foo": false, "newVal": "bar" }, { "foo": false, "newVal": "bar" }, { "foo": "some value" }, { "foo": "some other value" }] }, { "foo": "true" }, { "foo": false }, { "foo": "false" }] }], "Correct value"); }); it("By query with $exists", async () => { const dataArr = [{ "_id": "1", "arr": undefined }, { "_id": "2", "arr": [] }, { "_id": "3", "arr": [{here: true}] }, { "_id": "4", "arr": [{here: false}] }]; assert.strictEqual(dataArr.length, 4, "Number of documents is correct"); const updateResult = await update(dataArr, { "arr": { $exists: false } }, { $set: { "arr": [{here: true}] } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 4, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "arr": [{here: true}] }, { "_id": "2", "arr": [] }, { "_id": "3", "arr": [{here: true}] }, { "_id": "4", "arr": [{here: false}] }], "Correct value"); }); it("Using $one", async () => { const dataArr = [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "foo": false, "newVal": "bar" }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.strictEqual(dataArr[0].foo, false, "Correct value"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "foo": false, "newVal": "bar" }, { "_id": "2", "foo": true }], "Correct value"); }); it("Using $skipAssignment", async () => { const dataArr = [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "foo": false, "newVal": "bar" }, { "$skipAssignment": true }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.notStrictEqual(dataArr, updateResult, "Data has been immutably updated"); assert.notStrictEqual(dataArr[0], updateResult[0], "Data has been immutably updated"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }], "Correct value"); assert.deepStrictEqual(updateResult, [{ "_id": "1", "foo": false, "newVal": "bar" }], "Correct value"); }); it("Using $preFlight() false result", async () => { const dataArr = [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "foo": false, "newVal": "bar" }, { "$preFlight": (doc) => { return doc._id !== "1"; } }); assert.strictEqual(updateResult.length, 0, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.strictEqual(dataArr[0].foo, true, "Correct value"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }], "Correct value"); }); it("Using $preFlight() true result", async () => { const dataArr = [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "foo": false, "newVal": "bar" }, { "$preFlight": (doc) => { return doc._id === "1"; } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.strictEqual(dataArr[0].foo, false, "Correct value"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "foo": false, "newVal": "bar" }, { "_id": "2", "foo": true }], "Correct value"); }); it("Using $preFlight() true result, $postFlight() false result", async () => { const dataArr = [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "foo": false, "newVal": "bar" }, { "$preFlight": (doc) => { return doc._id === "1"; }, "$postFlight": (updatedDoc, originalDoc) => { return updatedDoc._id !== "1"; } }); assert.strictEqual(updateResult.length, 0, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.strictEqual(dataArr[0].foo, true, "Correct value"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }], "Correct value"); }); it("Using $preFlight() true result, $postFlight() true result", async () => { const dataArr = [{ "_id": "1", "foo": true }, { "_id": "2", "foo": true }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "foo": false, "newVal": "bar" }, { "$preFlight": (doc) => { return doc._id === "1"; }, "$postFlight": (updatedDoc, originalDoc) => { return updatedDoc._id === "1"; } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.strictEqual(dataArr[0].foo, false, "Correct value"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "foo": false, "newVal": "bar" }, { "_id": "2", "foo": true }], "Correct value"); }); }); describe("Operations", () => { describe("$inc", () => { it("Increase by value", async () => { const dataArr = [{ "_id": "1", "data": {"val": 1} }, { "_id": "2", "data": {"val": 12} }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "$inc": { "data.val": 1 } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.strictEqual(dataArr[0].data.val, 2, "Correct value"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "data": {"val": 2} }, { "_id": "2", "data": {"val": 12} }], "Correct value"); }); it("Decrease by value", async () => { const dataArr = [{ "_id": "1", "data": {"val": 1} }, { "_id": "2", "data": {"val": 12} }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "$inc": { "data.val": -1 } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "data": {"val": 0} }, { "_id": "2", "data": {"val": 12} }], "Correct value"); }); }); describe("$push", () => { it("Add item to array", async () => { const dataArr = [{ "_id": "1", "data": [{"val": 1}, {"val": 12}] }, { "_id": "2", "data": [] }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "$push": { "data": {"val": 24} } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "data": [{"val": 1}, {"val": 12}, {"val": 24}] }, { "_id": "2", "data": [] }], "Correct value"); }); }); describe("$pull", () => { it("Remove object from array", async () => { const dataArr = [{ "_id": "1", "data": [{"val": 1}, {"val": 12}, {"val": 24}] }, { "_id": "2", "data": [] }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "$pull": { "data": {"val": 12} } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "data": [{"val": 1}, {"val": 24}] }, { "_id": "2", "data": [] }], "Correct value"); }); it("Remove number from array", async () => { const dataArr = [{ "_id": "1", "data": [1, 12, 24] }, { "_id": "2", "data": [] }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "$pull": { "data": 12 } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "data": [1, 24] }, { "_id": "2", "data": [] }], "Correct value"); }); it("Remove first string from array", async () => { const dataArr = [{ "_id": "1", "data": ["1", "12", "12", "24", 1, 12, true] }, { "_id": "2", "data": [] }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "$pull": { "data": "12" } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "data": ["1", "12", "24", 1, 12, true] }, { "_id": "2", "data": [] }], "Correct value"); }); it("Remove first object from array", async () => { const dataArr = [{ "_id": "1", "data": [{"val": {"calc": 1, "foo": false}}, {"val": {"calc": 12, "foo": true}}, {"val": {"calc": 24, "foo": "bar"}}] }, { "_id": "2", "data": [] }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "$pull": { "data": {"val": {"calc": 12}} } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "data": [{"val": {"calc": 1, "foo": false}}, {"val": {"calc": 24, "foo": "bar"}}] }, { "_id": "2", "data": [] }], "Correct value"); }); }); describe("$pop", () => { it("Pops the first item from the end of the array", async () => { const dataArr = [{ "_id": "1", "data": [{"val": 1}, {"val": 12}, {"val": 24}] }, { "_id": "2", "data": [] }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "$pop": { "data": true } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "data": [{"val": 1}, {"val": 12}] }, { "_id": "2", "data": [] }], "Correct value"); }); }); describe("$unset", () => { it("Removes a key from an object at the specified path with array indexes", async () => { const dataArr = [{ "_id": "1", "data": [{"val": 1, "other": true}, {"val": 12}, {"val": 24}] }, { "_id": "2", "data": [] }]; assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); const updateResult = await update(dataArr, { "_id": "1" }, { "$unset": { "data.0.val": 1 } }); assert.strictEqual(updateResult.length, 1, "Number of documents is correct"); assert.strictEqual(dataArr.length, 2, "Number of documents is correct"); assert.strictEqual(dataArr[0]._id, "1", "Number of documents is correct"); assert.deepStrictEqual(dataArr, [{ "_id": "1", "data": [{"other": true}, {"val": 12}, {"val": 24}] }, { "_id": "2", "data": [] }], "Correct value"); const keys = Object.keys(dataArr[0].data[0]); assert.strictEqual(keys.indexOf("val"), -1, "Key is not present"); }); }); }); });