Reputation: 169
I have a couchbase database full of records that look like this:
{
"_class": "com.discussoftware.server.shared.model.bo.licenseBo",
"customerId": "A1A2",
"term": "SUBSCRIPTION",
"keys": {
"abc-123-evaluation": {
"active": true,
"expirationDate": 1669680000000,
"key": "abc-123-evaluation",
"name": "base product, floating, subscription",
"notBefore": 1667088000000,
"options": [
{
"option": "base",
"quantity": 1
},
{
"option": "secondary",
"quantity": 1
},
{
"option": "teriary",
"quantity": 1
},
{
"option": "ops",
"quantity": 1
}
],
"units": 1,
"version":
{
"major": 1,
"minor": 1,
"patch": 0
}
}
},
"master": "def-456",
"productId": "a1a2a3a4",
"supportId": "A1A2A3"
}
I can select based on the license key, with a statement like this:
SELECT *
FROM server1` AS d
WHERE ANY v in OBJECT_VALUES(d.keys)
SATISFIES v.expirationDate < 1713744000000
AND v.expirationDate > 1701734400000
AND v.version.major == 1
AND v.version.minor == 1
AND v.version.patch == 0
END;
But what I am having trouble with a writing an UPDATE that will let me update the version value.
I think the best one I have tried -- which returns 0 rows -- out of the 60 or so attempts, has been:
UPDATE `server1` AS d
SET v.version = {"major": 2, "minor": 1, "batch": = 0}
WHERE ANY v in OBJECT_VALUES(d.keys)
SATISFIES v.expirationDate < 1713744000000
AND v.expirationDate > 1701734400000
AND v.version.major == 1
AND v.version.minor == 1
AND v.version.patch == 0
END;
Upvotes: 1
Views: 71
Reputation: 7414
UPDATE `server1` AS d
SET v1.version.major = v1.version.major+1
FOR n:v1 IN d.`keys`
WHEN v1.expirationDate < 1713744000000
AND v1.expirationDate > 1701734400000
AND v1.version.major == 1
AND v1.version.minor == 1
AND v1.version.patch == 0
END
WHERE ANY v in OBJECT_VALUES(d.keys)
SATISFIES v.expirationDate < 1713744000000
AND v.expirationDate > 1701734400000
AND v.version.major == 1
AND v.version.minor == 1
AND v.version.patch == 0
END;
https://docs.couchbase.com/cloud/n1ql/n1ql-language-reference/update.html#update-for
Upvotes: 0
Reputation: 533
This works - but you'll need to hard-code and execute for all the values of abc-123-evaluation.
UPDATE `travel-sample` AS d
SET d.`keys`.`abc-123-evaluation`.version = {"major": 2, "minor": 1, "patch": 0}
WHERE
d.`keys`.`abc-123-evaluation`.expirationDate > 1669670000000 AND
d.`keys`.`abc-123-evaluation`.expirationDate < 1713744000000 AND
d.`keys`.`abc-123-evaluation`.version.major == 1 AND
d.`keys`.`abc-123-evaluation`.version.minor == 1 AND
d.`keys`.`abc-123-evaluation`.version.patch == 0
returning d
The predicate is indeed finding the documents, the issue is that the SET is (apparently) setting the values on the (intermediate?) object v, and not on the document.
When I insert your sample document in my bucket, make the changes below to your query, and run it, it returns 1 mutation. But when I fetch look at the document in couchbase, it is not changed. I assume that n1ql makes a temporary object v and updates that. Which is not helpful.
(1) keys needs to be in back-ticks, it's a reserved word. (2) remove the extraneous '=' in '"batch": = 0', and change name from batch to patch; (3) change the second(lower) date in the query so it is less than the one in the sample (4) remove OBJECT_VALUES (curiously, it seems to work the same with or without OBJECT_VALUES) (5) add , d.updated=1 just to show that the document gets updated. (but v.version does not).
insert into `travel-sample` (key, value) values ("1", {
"_class": "com.discussoftware.server.shared.model.bo.licenseBo",
"customerId": "A1A2",
"term": "SUBSCRIPTION",
"keys": {
"abc-123-evaluation": {
"active": true,
"expirationDate": 1669680000000,
"key": "abc-123-evaluation",
"name": "base product, floating, subscription",
"notBefore": 1667088000000,
"options": [
{
"option": "base",
"quantity": 1
},
{
"option": "secondary",
"quantity": 1
},
{
"option": "teriary",
"quantity": 1
},
{
"option": "ops",
"quantity": 1
}
],
"units": 1,
"version":
{
"major": 1,
"minor": 1,
"patch": 0
}
}
},
"master": "def-456",
"productId": "a1a2a3a4",
"supportId": "A1A2A3"
})
UPDATE `travel-sample` AS d
SET v.version = {"major": 2, "minor": 1, "batch": 0}
WHERE ANY v in d.`keys`
SATISFIES v.expirationDate < 1713744000000
AND v.expirationDate > 1669670000000
AND v.version.major == 1
AND v.version.minor == 1
AND v.version.patch == 0
END;
success just now 355.4ms 1 mutations
Upvotes: 1
Reputation: 26169
The simplest UPDATE
that I could think of to write to update that field is:
UPDATE records._default._default
USE KEYS "doc1"
SET `keys`.`abc-123-evaluation`.`version` = {"major":9, "minor":9, "patch":9}
Upvotes: 0