Search code examples
jsonzorbajsoniq

Insert into JSON using JSONiq


We are writing a JSONiq query to insert new properties into a JSON and return the updated JSON from the query.

Query:

jsoniq version "1.0";
let $users := {
  "name" : "Deadbeat Jim",
  "address" : "1 E 161st St, Bronx, NY 10451",
  "risk tolerance" : "high"
} 
insert json {"status" : "credit card declined"} into $users
return $users

users holds the input json, we are trying to add one more property using JSONiq insert command, as mentioned in JSONiq documentation here

We are getting below exception:

java.lang.RuntimeException: (no URI):13,1: static error [err:XPST0003]: invalid expression: syntax error, unexpected expression (missing comma "," between expressions?)

Questions :

  1. Is the query correct ? if not, How to make it correct syntactically/logically ?
  2. Are there any good resources available online for JSONiq with examples ?

Solution

  • Here are some more explanations:

    The way JSONiq updates work is identical to the way XQuery updates work. JSONiq updates are declarative: a JSONiq update program returns, in addition to an empty sequence in the data model, what is called a pending update list (PUL), which is a list of updates (deletions, replacements, renamings, insertions, etc) to be applied to some documents.

    JSONiq update has snapshot semantics, meaning that no side effects occur during the evaluation of the main expression. Instead, after the PUL has been computed, the engine may propagate the changes specified by the PUL to underlying storage (such as a file on disk, or a document store).

    A syntactically correct version of the question's example would be:

    jsoniq version "1.0";
    let $users := {
      "name" : "Deadbeat Jim",
      "address" : "1 E 161st St, Bronx, NY 10451",
      "risk tolerance" : "high"
    } 
    return insert json {"status" : "credit card declined"} into $users
    

    However, in this case, the PUL returned contains changes against a JSON object created on the fly, in memory. The lifetime of this object is only that of the evaluation of the query, so that this program simply has no visible effect.

    If the collection function is in some way mapped to a database in a document store like Couchbase or MongoDB (that is, if the engine is documented and configured to do this), the following query will semantically apply an update to this document store.

    jsoniq version "1.0";
    let $users := collection("users")[$$.name eq "Jim"]
    return insert json {"status" : "credit card declined"} into $users
    

    A copy-modify-return expression (also called transform expression like in XQuery, see other answer on this page) provides a way to apply changes in memory without losing them, and without any persistent storage. It:

    • creates a JSON object (as a copy of another), or an XML node, etc
    • modifies that object by applying the PUL obtained from the modify expression (important: this has no visible side effects, as only a copy is being modified)
    • returns the modified copy.

    For advanced users: in this case, the copy clause contains a constructor that builds a fresh object, so the optimizer can actually skip the copying.