Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions modules/n1ql/examples/dml/set-xattr.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[{
"a": {
"airportname": "San Francisco Intl",
"city": "San Francisco",
"country": "United States",
"faa": "SFO",
"geo": {
"alt": 13,
"lat": 37.618972,
"lon": -122.374889
},
"icao": "KSFO",
"id": 3469,
"type": "airport",
"tz": "America/Los_Angeles"
}
}]
8 changes: 8 additions & 0 deletions modules/n1ql/examples/dml/set-xattr.n1ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
UPDATE airport AS a
SET META(a).xattrs.metadata = {
"lastUpdatedBy": "Admin",
"reviewed": true,
"notes": "Updated terminal info"
}
WHERE a.faa = "SFO"
RETURNING a;
3 changes: 3 additions & 0 deletions modules/n1ql/examples/dml/unset-xattr.n1ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
UPDATE airport AS a
UNSET META(a).xattrs.metadata
WHERE a.faa = "SFO";
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@ Note that this property gives correct results only when used in a xref:n1ql-lang
id::
include::./metafun.adoc[tag=metadata-id]

xattrs::
include::./metafun.adoc[tag=metadata-xattr]
+
NOTE: Starting with Couchbase Server 8.0, you can index any number of XATTR fields using the xref:n1ql:n1ql-language-reference/createindex.adoc[CREATE INDEX] statement.

The `META()` function does not require a keyspace parameter when creating an index, since it implicitly uses the keyspace being indexed.


== Examples

include::ROOT:partial$query-context.adoc[tag=section]
Expand Down
39 changes: 37 additions & 2 deletions modules/n1ql/pages/n1ql-language-reference/insert.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,22 @@ You can insert NULL, empty, or MISSING values.

options::
[Optional] An object representing the metadata to be set for the inserted document.
Only the `expiration` attribute has any effect; any other attributes are ignored.
Only the listed attributes have any effect; the statement ignores the others.

expiration:::
An integer, or an expression resolving to an integer, representing the {document-expiration}[document expiration] in seconds.
+
If the document expiration is not specified, it defaults to `0`, meaning the document expiration is the same as the {bucket-expiration}[bucket or collection expiration].

xattrs:::
An object containing top-level extended attribute (XATTR) names and their corresponding JSON values.
+
The object includes only the attributes you want to add or update and does not affect other existing attributes.
For each atttribute, you must provide its complete value.
You cannot specify or update individual nested fields, as each attribute is updated as a whole.
+
NOTE: Starting with Couchbase Server 8.0, you can include up to 15 XATTRs per query.

For examples illustrating the VALUES clause, see <<insert-examples>>.

[[insert-select]]
Expand All @@ -263,13 +272,22 @@ If the VALUE is omitted, the entire JSON document generated by the SELECT statem

options::
[Optional] An object representing the metadata to be set for the inserted document.
Only the `expiration` attribute has any effect; any other attributes are ignored.
Only the listed attributes have any effect; the statement ignores the others.

expiration:::
An integer, or an expression resolving to an integer, representing the {document-expiration}[document expiration] in seconds.
+
If the document expiration is not specified, it defaults to `0`, meaning the document expiration is the same as the {bucket-expiration}[bucket or collection expiration].

xattrs:::
An object containing top-level extended attribute (XATTR) names and their corresponding JSON values.
+
The object includes only the attributes you want to add or update and does not affect other existing attributes.
For each atttribute, you must provide its complete value.
You cannot specify or update individual nested fields, as each attribute is updated as a whole.
+
NOTE: Starting with Couchbase Server 8.0, you can include up to 15 XATTRs per query.

select:: <<select-statement>> icon:caret-down[]

[[select-statement]]
Expand Down Expand Up @@ -988,6 +1006,23 @@ curl -v http://localhost:8093/query/service -u Administrator:password \
----
====

[[example-xattr]]
.Insert a document with an extended attribute (XATTR)
====
Insert a document into the `airline` keyspace with an extended attribute, `metadata`.

.Query
[source,sqlpp]
----
INSERT INTO airline (KEY, VALUE, OPTIONS)
VALUES ("airline:1402",
{ "callsign": "MY-AIR",
"country": "United States",
"type": "airline" },
{ "xattrs": { "metadata": { "created_by": "admin", "created_at": "2025-08-05" } } });
----
====

[#insert-explain-plan]
== Explain Plan

Expand Down
18 changes: 18 additions & 0 deletions modules/n1ql/pages/n1ql-language-reference/metafun.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,24 @@ type::: Value for the type of document; currently only `json` is supported.
This property is not indexable.
If you attempt to build an index on this property, an error is returned.

xattrs:::
// tag::metadata-xattr[]
Value representing extended attributes (XATTRs) of a document.
+
--
To access XATTRs, use the syntax `META().xattrs.<attribute>[.<path>]`, where:

* `<attribute>` is a top-level attribute name or key of the XATTR object.
* `<path>` is an optional subpath within that attribute.
--
+
While you can create an index on a specific extended attribute like `META().xattrs.attr1`, you cannot create an index on the entire `META().xattrs` object itself.
// end::metadata-xattr[]
+
Attempting to select the entire `META().xattrs` object will return an empty result.
+
NOTE: Starting with Couchbase Server 8.0, you can include up to 15 XATTRs per query.

=== Return Value

The bare function returns a JSON object containing the specified document's metadata.
Expand Down
58 changes: 52 additions & 6 deletions modules/n1ql/pages/n1ql-language-reference/update.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -168,19 +168,27 @@ The value may be a generic expression term, a subquery, or an expression that re

update-for:: <<update-for>> icon:caret-down[]

The SET clause also supports alternative arguments which enable you to set the expiration of the document.
The SET clause also supports alternative arguments which enable you to set the expiration and extended attributes of the document.

[horizontal]
meta::
A {meta}[META().expiration] expression specifying the expiration property of the document being updated.
meta::

expiration::
An integer, or an expression resolving to an integer, representing the {document-expiration}[document expiration] in seconds.
A META() expression specifying the document metadata.
+
To set the expiration property, use {meta}[META().expiration].
+
To set extended attributes (XATTR), use {meta}[META().xattrs.<attribute>[.<path>\]]

expiration:::
An integer, or an expression resolving to an integer, representing the {document-expiration}[document expiration] in seconds.
+
[NOTE]
If the document expiration is not specified, the document expiration is set according to the request-level {preserve_expiry}[preserve_expiry] parameter.
If this is `true`, the existing document expiration is preserved; if `false`, the document expiration defaults to `0`, meaning the document expiration is the same as the {bucket-expiration}[bucket or collection expiration].

xattrs:::
An object containing one or more extended attribute (XATTR) names as top-level keys and their corresponding JSON values.

[[unset-clause]]
=== UNSET Clause

Expand All @@ -193,12 +201,22 @@ image::n1ql-language-reference/unset-clause.png["Syntax diagram: refer to source

Removes the specified attribute from the document.

[horizontal.compact]
[horizontal]
path::
A <<path,path>> specifying the attribute to be removed.

update-for:: <<update-for>> icon:caret-down[]

meta-xattr::
An expression specifying the extended attribute (XATTR) to be removed.
+
--
The format is {meta}[META().xattrs.<attribute>[.<path>\]], where:

* `<attribute>` is a top-level attribute name or key of the XATTR object.
* `<path>` is an optional subpath within that attribute.
You can directly reference individual fields in composite XATTR values through the nested path.
--
[NOTE]
You cannot use the UNSET clause to unset the document expiration.
To unset the document expiration, set the document expiration to `0`.
Expand Down Expand Up @@ -410,3 +428,31 @@ Alternatively, if the request-level {preserve_expiry}[preserve_expiry] parameter
include::example$dml/update-unset-expire-alt.n1ql[]
----
====

[[example-10]]
.Update a document and set an extended attribute (XATTR)
====

.Query
[source,sqlpp]
----
include::example$dml/set-xattr.n1ql[]
----

.Result
[source,json]
----
include::example$dml/set-xattr.jsonc[]
----
====

[[example-11]]
.Update a document and unset an extended attribute (XATTR)
====

.Query
[source,sqlpp]
----
include::example$dml/unset-xattr.n1ql[]
----
====
16 changes: 14 additions & 2 deletions modules/n1ql/pages/n1ql-language-reference/upsert.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,15 @@ Also enables you to set the {document-expiration}[expiration] of the upserted do
For details, refer to {values-clause}[VALUES Clause].

[NOTE]
When updating a document, if the document expiration is not specified, the document expiration is set according to the request-level {preserve_expiry}[preserve_expiry] parameter.
====
* When updating a document, if the document expiration is not specified, the document expiration is set according to the request-level {preserve_expiry}[preserve_expiry] parameter.
If this is `true`, the existing document expiration is preserved; if `false`, the document expiration defaults to `0`, meaning the document expiration is the same as the {bucket-expiration}[bucket or collection expiration].

* When adding or updating extended attributes (XATTRs), you must provide the complete value for each attribute.
You cannot specify or update individual nested fields, as each attribute is updated as a whole.
For example, if an existing XATTR named `a` has the value `{"b":1}`, an UPSERT operation with the option `{"xattrs":{"a":{"c":1}}}` completely replaces the value of `a` with `{"c":1}`.
====

[[insert-select]]
=== Insert Select

Expand All @@ -199,9 +205,15 @@ Also enables you to set the {document-expiration}[expiration] of the upserted do
For details, refer to {insert-select}[Insert Select].

[NOTE]
When updating a document, if the document expiration is not specified, the document expiration is set according to the request-level {preserve_expiry}[preserve_expiry] parameter.
====
* When updating a document, if the document expiration is not specified, the document expiration is set according to the request-level {preserve_expiry}[preserve_expiry] parameter.
If this is `true`, the existing document expiration is preserved; if `false`, the document expiration defaults to `0`, meaning the document expiration is the same as the {bucket-expiration}[bucket or collection expiration].

* When adding or updating extended attributes (XATTRs), you must provide the complete value for each attribute.
You cannot specify or update individual nested fields, as each attribute is updated as a whole.
For example, if an existing XATTR named `a` has the value `{"b":1}`, an UPSERT operation with the option `{"xattrs":{"a":{"c":1}}}` completely replaces the value of `a` with `{"c":1}`.
====

////
[[select-statement]]
==== SELECT Statement
Expand Down
6 changes: 3 additions & 3 deletions modules/n1ql/partials/grammar/dml.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ returning-clause ::= 'RETURNING' (result-expr (',' result-expr)* |
/* end::returning-clause[] */

/* tag::set-clause[] */
set-clause ::= 'SET' ( meta '=' expiration | path '=' expr update-for? )
( ',' ( meta '=' expiration | path '=' expr update-for? ) )*
set-clause ::= 'SET' ( path '=' expr update-for? | meta '=' ( expiration | xattrs ) )
( ',' ( path '=' expr update-for? | meta '=' ( expiration | xattrs ) ) )*
/* end::set-clause[] */

/* tag::unset-clause[] */
unset-clause ::= 'UNSET' path update-for? (',' path update-for?)*
unset-clause ::= 'UNSET' ( path update-for? | meta-xattr ) ( ',' ( path update-for? | meta-xattr ) )*
/* end::unset-clause[] */

/* tag::update-for[] */
Expand Down