Skip to content

Bulk Update Key-Value Collection with RestQL

This tutorial is about using RestQL to bulk update Key-Value Collection data.

Note

If you are new to Macrometa GDN, we strongly recommend reading Essentials of Macrometa GDN.

Pre-requisite

Let's assume your

Driver 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.
With Yarn or NPM

    yarn add jsc8
    (or)
    npm install jsc8

If you want to use the driver outside of the current directory, you can also install it globally using the `--global` flag:

    npm install --global jsc8

From source,

    git clone https://github.com/macrometacorp/jsc8.git
    cd jsC8
    npm install
    npm run dist

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));
        });
    }
}

const EMAIL = "[email protected]";
const PASSWORD = "xxxxxx";
const FEDERATION_URL = "https://api-gdn.prod.macrometa.io";
const FABRIC_NAME = "_system";
const COLLECTION_NAME = "superhero";

//Variables
const inputDocs = [
    { "_key": "[email protected]", "value": "James"},
    { "_key": "[email protected]", "value": "Han"},
    { "_key": "[email protected]", "value": "Bruce"}
];

const updateKeys = ["[email protected]", "[email protected]"];
const updateKeyValue = {
    "[email protected]": { key: "[email protected]",  value: "Bruce Wayne"},
    "[email protected]": { key: "[email protected]", value: "James T Kirk"}
};

//Queries
const insertData = `FOR doc in @InputDocs \
INSERT {"_key": doc._key, "value": doc.value} IN ${COLLECTION_NAME}`;

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

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

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

        /* -------------------- Login ([email protected]/xxxxxxx) -------------------- */
        await connection.login(EMAIL, PASSWORD);
        console.log("Login Successfully using", EMAIL);

        /* -------------------------- Create Doc Collection ------------------------- */
        const collection = await connection.req(`/_fabric/${FABRIC_NAME}/_api/kv/${COLLECTION_NAME}`, {
            body: { stream: false },
            method: "POST",
        });

        console.log("COLLECTION CREATED SUCCESSFULLY", collection);

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

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

        console.log("Queries Saved Successfully");

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

        console.log("------- Execute the RestQl 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");
    } catch (e) {
        console.error(e);
    }
};

run();
from c8 import C8Client

fed_url = "gdn.paas.macrometa.io"
guest_mail = "[email protected]"
guest_password = "xxxxxx"
geo_fabric = "_system"
collection_name = "superhero"

inputDocs = [
    { "_key": "[email protected]", "value": "James"},
    { "_key": "[email protected]", "value": "Han"},
    { "_key": "[email protected]", "value": "Bruce"}
]

updateKeys = ["[email protected]", "[email protected]"]
updateKeyValue = {
    "[email protected]": { "key": "[email protected]",  "value": "Bruce Wayne"},
    "[email protected]": { "key": "[email protected]", "value": "James T Kirk"}
}

insert_data_query = (
    "FOR doc in @InputDocs INSERT {'_key': doc._key, 'value': doc.value} IN %s"
    % collection_name
)
get_data_query = "FOR doc IN %s RETURN doc" % collection_name
update_data_query = (
    "FOR i IN %s FILTER i._key IN @updateKeys UPDATE i with { value: (i._key == @updateKeyValue[i._key].key) ? @updateKeyValue[i._key].value : i.value } IN %s"
    % (collection_name, collection_name)
)

insert_data = {
    "query": {
        "name": "insertRecord",
        "value": insert_data_query,
    }
}
get_data = {"query": {"name": "getRecords", "value": get_data_query}}
update_data = {"query": {"name": "updateRecord", "value": update_data_query}}

if __name__ == "__main__":

    print("\n ------- CONNECTION SETUP  ------")
    print("tenant: {}, geofabric:{}".format(guest_mail, geo_fabric))
    client = C8Client(
        protocol="https",
        host=fed_url,
        port=443,
        email=guest_mail,
        password=guest_password,
        geofabric=geo_fabric,
    )

    print("\n ------- CREATE GEO-REPLICATED COLLECTION  ------")
    if client.has_collection(collection_name):
        print("Collection exists")
    else:
        employees = client.create_collection_kv(collection_name)
    print("Created collection: {}".format(collection_name))

    print("\n ------- CREATE RESTQLs  ------")
    client.create_restql(insert_data)
    client.create_restql(get_data)
    client.create_restql(update_data)
    print("Created RESTQLs:{}".format(client.get_restqls()))

    print("\n ------- EXECUTE RESTQLs ------")
    print("Insert data....")
    response = client.execute_restql(
        "insertRecord", {"bindVars": {"InputDocs": inputDocs}}
    )

    print("Get data....")
    response = client.execute_restql("getRecords")
    print(response)

    print("Update data....")
    response = client.execute_restql(
        "updateRecord",
        {"bindVars": {"updateKeys": updateKeys, "updateKeyValue": updateKeyValue}},
    )

    print("Get data....")
    response = client.execute_restql("getRecords")
    print(response)

    print("\n ------- DONE  ------")
const jsc8 = require('jsc8');

// Create a authenticated instance with Token / Apikey
// const client = new jsc8({url: "https://gdn.paas.macrometa.io", token: "XXXX", fabricName: '_system'});
// const client = new jsc8({url: "https://gdn.paas.macrometa.io", apiKey: "XXXX", fabricName: '_system'});
const client = new jsc8("https://gdn.paas.macrometa.io");

//Variables
const collectionName = "superhero" + Math.floor(1000 + Math.random() * 9000).toString();

const inputDocs = [
    { "_key": "[email protected]", "value": "James"},
    { "_key": "[email protected]", "value": "Han"},
    { "_key": "[email protected]", "value": "Bruce"}
];

const updateKeys = ["[email protected]", "[email protected]"];
const updateKeyValue = {
    "[email protected]": { key: "[email protected]",  value: "Bruce Wayne"},
    "[email protected]": { key: "[email protected]", value: "James T Kirk"}
};

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

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

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

async function restqldemo() {
    /* Authenticate client instance with username and password */
    console.log("------- AUTHENTICATE CLIENT INSTANCE WITH USERNAME AND PASSWORD  ------");
    await client.login("[email protected]", "xxxxxx");

    /* Create Collection */
    console.log("------- CREATE GEO-REPLICATED COLLECTION  ------");

    const collection = await client.createKVCollection(collectionName);

    console.log("Collection " + collectionName + " created.\n", collection);

    /* Save RestQl Queries */
    console.log("------- SAVING THE QUERIES  ------");

    await client.createRestql("insertData", insertData, {});
    await client.createRestql("getData", getData, {});
    await client.createRestql("updateData", updateData, {});

    console.log("Saved Queries Successfully\n");

    /* Execute RestQl Queries */
    console.log("------- EXECUTING THE QUERIES  ------");

    await client.executeRestql("insertData", {
        InputDocs: inputDocs
    });

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

    const res = await client.executeRestql("getData");

    console.log("Output of get data query:");
    console.log(res.result);
    console.log("\n");

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

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

    const data = await client.executeRestql("getData");

    console.log("Output of get data query after update:");
    console.log(data.result);
    console.log("\n");
}

restqldemo().then(console.log("Starting Execution"));