Write Queries
In the following sample code, db
represents the state variable of your database instance. For reference, see Initialize WeaveDB
collection_name
refers to the string value that contains the name of your collection, and doc_id
refers to the string value that contains the unique identifier of a document from the collection.
The differences between set
, upsert
, and update
are:
set
- ifdoc_id
exists in the collection, it will override the entire document, deleting all previous properties or it will add a new document ifdoc_id
does not exist.update
- ifdoc_id
exists in the collection, it will merge the new data with the existing document or the query will fail if the assigneddoc_id
does not exist.upsert
- ifdoc_id
exists in the collection, it will merge the new data with the existing document or it will add a new document ifdoc_id
does not exist.
add
Adds a new document to the given collection.
await db.add({ age: 20, name: "Bob" }, collection_name)
The document ID will be assigned in a random yet deterministic manner.
set
Adds a new document to the given collection and allows you to choose its document ID.
await db.set({ age: 20, name: "Bob" }, collection_name, doc_id)
This will reset the whole document if the doc_id
already exists.
upsert
Combines the functions of update
and set
. It merges the new data with an existing document or creates a new document if it does not already exist.
await db.upsert({ age: 20, name: "Bob" }, collection_name, doc_id)
update
Updates a specific document within a collection. This command only modifies existing documents and does not create new ones.
await db.update({ age: 25 }, collection_name, doc_id)
This will fail if the doc_id
does not exist.
Special Operations
The following is a list of special operations. WeaveDB has shortcuts for common operations that are only available with the SDK and not with the web console terminal at the moment.
Delete a field
Removes a specified field from a document in a collection. Useful for cleaning up data or adhering to data structure changes.
await db.update({ age: db.del() }, collection_name, doc_id)
Increase a field
Increments the value of a numeric field in a document by a specified amount. Ideal for updating counters or cumulative values.
await db.update({ age: db.inc(5) }, collection_name, doc_id)
Decrease a field
Decrements the value of a numeric field in a document by a specified amount. Useful for decrementing counters or adjusting values downwards.
await db.update({ age: db.inc(-5) }, collection_name, doc_id)
Array union
Adds unique elements to an array field in a document. Prevents duplication and is useful for managing lists without redundant entries.
await db.update({ chars: db.union([ "a", "b", "c", "d" ]) }, collection_name, doc_id)
Array remove
Removes specified elements from an array field in a document. Ideal for filtering out unwanted items from a list.
await db.update({ chars: db.remove([ "b", "c" ]) }, collection_name, doc_id)
Set block timestamp
Sets the field to the current block timestamp.
await db.update({ date: db.ts() }, collection_name, doc_id)
Set signer Ethereum address
Sets the field to the signer's wallet address.
await db.update({ address: db.signer() }, collection_name, doc_id)
signer
will always be in lowercase if it's an EVM wallet address. WeaveDB contract converts everything to lowercase to use them internally.
In regard to Arweave wallet addresses, the case will be retained, because it's RSA hashes and the case matters.
data()
Replace a field with relayer's extra data
Feature added in contract version 0.28.12
// icon field will be automatically replaced with `image.png` from the relayer
const query = await db.sign(
"update",
{ icon: db.data("extra_data_key") },
collection_name,
doc_id,
{ jobID: "jobID", evm: signer_wallet },
)
await db.relay("jobID", query, { extra_data_key: "image.png" }, { evm: relayer_wallet })
zkp()
Feature added in contract version 0.38.0
Verify Zero Knowledge Proof with PolygonID (opens in a new tab)
await db.update({ userID: db.zkp(proof, pub_signals) }, collection_name, doc_id)
/*
userID will be replaced with the following
you should modify it further in access control rules
{
valid,
pub_signals: {
value,
merklizedn,
userID,
issuerAuthState,
requestID,
issuerID,
isRevocationChecked,
issuerClaimNonRevState,
timestamp,
claimSchema,
claimPathNotExists,
claimPathKey,
slotIndex,
operator,
},
}
*/
delete
Removes a specified document from a collection.
await db.delete(collection_name, doc_id)
batch
An atomic batch is a feature that allows you to perform multiple read and write operations as a single, atomic unit.
Atomic means that all the operations within the batch are either fully completed or completely aborted. If any of the write operations fail, none of the changes will be applied to the database, ensuring data integrity.
await db.batch([
["set", { name: "Bob" }, "people", "Bob"],
["upsert", { name: "Alice" }, "people", "Alice"],
["delete", "John"]
])
You can use batch only if all the queries are by the same signer. If you have multiple signers, use bundle.
Admin queries can be batch-executed as well:
await db.batch([
["setSchema", schema, "people"],
["setRules", rules, "people"],
["addOwner", "0xABC"]
], { ar : admin_arweave_wallet })
bundle
Bundle multiple queries from multiple signers
const query1 = await db.sign("set", {name: "Bob"}, "people", "Bob", {evm: wallet1})
const query2 = await db.sign("set", {name: "Alice"}, "people", "Alice", {ii: wallet2})
const query3 = await db.sign("set", {name: "Beth"}, "people", "Beth", {ar: wallet3})
await db.bundle([query1, query2, query3], {ar: bundler_wallet})
sign
Sign a query without sending a transaction:
await db.sign("set", {name: "Bob", age: 20}, collection_name, doc_id)
relay
Relay a query allows for the execution of a signed operation with additional parameters. Useful for scenarios where you need to delegate the execution of a database operation, potentially with added data.
const param = await db.sign("set", {name: "Bob"}, collection_name, doc_id)
const extra = { age: 20 }
await db.relay("jobID", param, extra, {evm: relayer_wallet})