Skip to main content

Bulk Update with RestQL

This tutorial is about using RestQL to bulk update document Collection data.

Pre-requisite

Let's assume your

  • Tenant name is nemo@nautilus.com and
  • User password is xxxxxx.

SDK download

pyC8 requires Python 3.5+. Python 3.6 or higher is recommended

To install pyC8, simply run

$ pip3 install pyC8

or, if you prefer to use conda:

conda install -c conda-forge pyC8

or pipenv:

pipenv install --pre pyC8

Once the installation process is finished, you can begin developing applications in Python.

Code Sample

class APIRequest {
_headers = {
Accept: "application/json",
"Content-Type": "application/json"
};

constructor(url) {
this._url = url;
}

login(email, password) {
const endpoint = "/_open/auth";
const self = this;
return new Promise(function (resolve, reject) {
self.req(endpoint, {
body: { email, password },
method: "POST"
})
.then(({ jwt, ...data }) => {
self._headers.authorization = `bearer ${jwt}`;
resolve(data);
})
.catch(reject);
});
}

_handleResponse(response, resolve, reject) {
if (response.ok) {
resolve(response.json());
} else {
reject(response);
}
}

req(endpoint, { body, ...options } = {}) {
const self = this;
return new Promise(function (resolve, reject) {
fetch(self._url + endpoint, {
headers: self._headers,
body: body ? JSON.stringify(body) : undefined,
...options,
}).then((response) => self._handleResponse(response, resolve, reject));
});
}
}

// Variables
const email = "nemo@nautilus.com";
const password = "xxxxxx";
const federationUrl = "https://api-smoke1.eng.macrometa.io";
const fabricName = "_system";
const collectionName = "superhero" + Math.floor(1000 + Math.random() * 9000).toString();
const jamesKey = "james.kirk" + Math.floor(1000 + Math.random() * 9000).toString();
const bruceKey = "bruce.wayne" + Math.floor(1000 + Math.random() * 9000).toString();
const barryKey = "barry.allen" + Math.floor(1000 + Math.random() * 9000).toString();

const inputDocs = [
{ "_key": jamesKey, "firstname": "James", "lastname": "Kirk", "email": "james.kirk@macrometa.io", "zipcode": "12312" },
{ "_key": bruceKey, "firstname": "Bruce", "lastname": "Wayne", "email": "bruce.wayne@macrometa.io", "zipcode": "12345" }
];

const updateKeys = [jamesKey, bruceKey];
const updateKeyValue = {
bruceKey: { key: bruceKey, zipcode: "22222" },
jamesKey: { key: jamesKey, zipcode: "55555" }
};

// Queries
const insertData = `FOR doc in @InputDocs \
INSERT { "firstname":doc.firstname, "lastname":doc.lastname, "email":doc.email, "zipcode":doc.zipcode, "_key": doc._key } IN ${collectionName}`;

const getData = `FOR doc IN ${collectionName} RETURN doc`;

const updateData = `FOR i IN ${collectionName} \
FILTER i._key IN @updateKeys \
UPDATE i with { zipcode: (i._key == @updateKeyValue[i._key].key) ? @updateKeyValue[i._key].zipcode : i.zipcode } IN ${collectionName}`;

const updatedInsertData = `INSERT
{ "firstname": "Barry", "lastname": "Allen", "email": "barry.allen@macrometa.io", "zipcode": "44444", "_key": @barryKey } IN ${collectionName}`;

const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}

const run = async function () {
try {
const connection = new APIRequest(federationUrl);

/* -------------------- Login (nemo@nautilus.com/xxxxxxx) -------------------- */
await connection.login(email, password);
console.log("Login Successfully using ", email);

/* -------------------------- Create Doc Collection ------------------------- */
try {
const collection = await connection.req(`/_fabric/${fabricName}/_api/collection`, {
body: { name: collectionName },
method: "POST"
});
console.log("Collection " + collectionName + " created.\n", collection);
} catch (e) {
if (e.status === 409) {
console.log("Collection already exists, skipping creation");
} else {
console.log("Create collection failed");
throw e;
}
}

/* ------------------------ Saving a query ----------------------- */
const saveRestQlQuery = (queryName, query, parameters) =>
connection.req(`/_fabric/${fabricName}/_api/restql`, {
body: {
query: {
name: queryName,
value: query,
parameter: parameters
}
},
method: "POST"
});

console.log("------- Save the Queries ------");
await saveRestQlQuery("insertData", insertData, {});
await saveRestQlQuery("getData", getData, {});
await saveRestQlQuery("updateData", updateData, {});

console.log("Queries Saved Successfully");

/* ----------------------- Executing a query ---------------------- */
const executeRestql = (queryName, parameter) =>
connection.req(`/_fabric/${fabricName}/_api/restql/execute/${queryName}`, {
body: {
bindVars: parameter
},
method: "POST"
});

await sleep(2000);
console.log("------- Execute the Queries ------");

await executeRestql("insertData", {
InputDocs: inputDocs
});
console.log("Data Inserted \n");

console.log("Get Data...");

const dataBeforeUpdate = await executeRestql("getData");
console.log(dataBeforeUpdate.result);
console.log("\n");

await executeRestql("updateData", {
updateKeys,
updateKeyValue
});

console.log("Data updated \n");

const dataAfterUpdate = await executeRestql("getData");
console.log(dataAfterUpdate.result);
console.log("\n");

/* ------------------------ Updating a query ----------------------- */
const updateRestQlQuery = (queryName, query, parameters) =>
connection.req(`/_fabric/${fabricName}/_api/restql/${queryName}`, {
body: {
query: {
value: query,
parameter: parameters
}
},
method: "PUT"
});

console.log("------- Updating the insertData query ------");
await updateRestQlQuery("insertData", updatedInsertData, {});
console.log("Query updated successfully");

await sleep(2000);
await executeRestql("insertData", {
barryKey
});
console.log("New data inserted with the updated insertData query\n");

const resultAfterUpdate = await executeRestql("getData");
console.log(resultAfterUpdate.result);
console.log("\n");

const deleteRestQl = (queryName) =>
connection.req(`/_fabric/${fabricName}/_api/restql/${queryName}`, {
method: "DELETE"
});

console.log("------- Deleting the insertData, getData, and updateData queries ------");
await deleteRestQl("insertData");
await deleteRestQl("getData");
await deleteRestQl("updateData");
console.log("RestQls deleted successfully");

} catch (e) {
console.log("Error caught while executing RestQL demo: ");
console.error(e);
}
};

run();