Work with . and & in field names
You must use & to escape any . or & in field names when the field is used in a filter, sort, projection, update, or indexing clause.
Dot notation, which is used to reference nested fields, should not be escaped.
For example, in the following document, you would use escaping like this: areas.r&&d, costs.price&.usd, and costs.price&.cad.
{
"areas": {
"r&d": true,
"design": false
},
"costs": {
"price.usd": 100,
"price.cad": 90
}
}
You should not escape . or & in field names when you insert or replace a document.
For example:
-
Python
-
TypeScript
-
Java
-
curl
The following example uses untyped documents or rows, but you can define a client-side type for your collection to help statically catch errors. For examples, see Typing support.
from astrapy import DataAPIClient
from astrapy.constants import SortMode
# Get an existing collection
client = DataAPIClient()
database = client.get_database("API_ENDPOINT", token="APPLICATION_TOKEN")
collection = database.get_collection("COLLECTION_NAME")
# Find a document
result = collection.find_one_and_replace(
{
"$and": [
{"areas.r&&d": False},
{"costs.price&.usd": {"$lt": 300}},
]
},
{
"areas": {"r&d": False, "design": True},
"costs": {"price.usd": 100, "price.cad": 90},
},
projection={"areas.r&&d": True, "costs.price&.usd": True},
sort={
"areas.r&&d": SortMode.ASCENDING,
"costs.price&.usd": SortMode.DESCENDING,
},
)
print(result)
You can also use the escape_field_names function provided by the client:
from astrapy import DataAPIClient
from astrapy.constants import SortMode
from astrapy.utils.document_paths import escape_field_names
# Get an existing collection
client = DataAPIClient()
database = client.get_database("API_ENDPOINT", token="APPLICATION_TOKEN")
collection = database.get_collection("COLLECTION_NAME")
# Find a document
result = collection.find_one_and_replace(
{
"$and": [
{escape_field_names("areas", "r&d"): False},
{escape_field_names("costs", "price.usd"): {"$lt": 300}},
]
},
{
"areas": {"r&d": False, "design": True},
"costs": {"price.usd": 100, "price.cad": 90},
},
projection={
escape_field_names("areas", "r&d"): True,
escape_field_names("costs", "price.usd"): True,
},
sort={
escape_field_names("areas", "r&d"): SortMode.ASCENDING,
escape_field_names("costs", "price.usd"): SortMode.DESCENDING,
},
)
print(result)
import { DataAPIClient } from "@datastax/astra-db-ts";
// Get an existing collection
const client = new DataAPIClient();
const database = client.db("API_ENDPOINT", {
token: "APPLICATION_TOKEN",
});
const collection = database.collection("COLLECTION_NAME");
// Find a document
(async function () {
const result = await collection.findOneAndReplace(
{
$and: [{ "areas.r&&d": false }, { "costs.price&.usd": { $lt: 300 } }],
},
{
areas: {
"r&d": false,
design: true,
},
costs: {
"price.usd": 100,
"price.cad": 90,
},
},
{
projection: { "areas.r&&d": true, "costs.price&.usd": true },
sort: {
"areas.r&&d": 1,
"costs.price&.usd": -1,
},
},
);
console.log(result);
})();
You can also use the escapeFieldNames function provided by the client:
import { DataAPIClient, escapeFieldNames } from "@datastax/astra-db-ts";
// Get an existing collection
const client = new DataAPIClient();
const database = client.db("API_ENDPOINT", {
token: "APPLICATION_TOKEN",
});
const collection = database.collection("COLLECTION_NAME");
// Find a document
(async function () {
const result = await collection.findOneAndReplace(
{
$and: [
{ [escapeFieldNames("areas", "r&d")]: false },
{ [escapeFieldNames("costs", "price.usd")]: { $lt: 300 } },
],
},
{
areas: {
"r&d": false,
design: true,
},
costs: {
"price.usd": 100,
"price.cad": 90,
},
},
{
projection: {
[escapeFieldNames("areas", "r&d")]: true,
[escapeFieldNames("costs", "price.usd")]: true,
},
sort: {
[escapeFieldNames("areas", "r&d")]: 1,
[escapeFieldNames("costs", "price.usd")]: -1,
},
},
);
console.log(result);
})();
import com.datastax.astra.client.DataAPIClient;
import com.datastax.astra.client.collections.Collection;
import com.datastax.astra.client.collections.definition.documents.Document;
import com.datastax.astra.client.core.query.Filter;
import com.datastax.astra.client.core.query.Filters;
import java.util.Map;
import java.util.Optional;
public class Example {
public static void main(String[] args) {
// Get an existing collection
Collection<Document> collection =
new DataAPIClient("APPLICATION_TOKEN")
.getDatabase("API_ENDPOINT")
.getCollection("COLLECTION_NAME");
// Find a document
Filter filter =
Filters.and(Filters.eq("areas.r&&d", false), Filters.lt("costs.price&.usd", 300));
CollectionFindOneAndReplaceOptions options =
new CollectionFindOneAndReplaceOptions()
.sort(Sort.ascending("areas.r&&d"), Sort.descending("costs.price&.usd"))
.projection(Projection.include("areas.r&&d", "costs.price&.usd"));
Document newDocument =
new Document()
.append(
"areas",
Map.of(
"r&d", false,
"design", true))
.append(
"costs",
Map.of(
"price.usd", 100,
"price.cad", 90));
Optional<Document> result = collection.findOneAndReplace(filter, newDocument, options);
System.out.println(result);
}
}
You can also use the escapeFieldNames function provided by the client:
import com.datastax.astra.client.DataAPIClient;
import com.datastax.astra.client.collections.Collection;
import com.datastax.astra.client.collections.definition.documents.Document;
import com.datastax.astra.client.core.query.Filter;
import com.datastax.astra.client.core.query.Filters;
import java.util.Map;
import java.util.Optional;
import com.datastax.astra.internal.utils.EscapeUtils;
import com.datastax.astra.client.collections.commands.options.CollectionFindOneAndReplaceOptions;
public class Example {
public static void main(String[] args) {
// Get an existing collection
Collection<Document> collection =
new DataAPIClient("APPLICATION_TOKEN")
.getDatabase("API_ENDPOINT")
.getCollection("COLLECTION_NAME");
// Find a document
Filter filter =
Filters.and(Filters.eq(EscapeUtils.escapeFieldNames("areas", "r&d"), false), Filters.lt(EscapeUtils.escapeFieldNames("costs", "price.usd"), 300));
CollectionFindOneAndReplaceOptions options =
new CollectionFindOneAndReplaceOptions()
.sort(Sort.ascending(EscapeUtils.escapeFieldNames("areas", "r&d")), Sort.descending(EscapeUtils.escapeFieldNames("costs", "price.usd")))
.projection(Projection.include(EscapeUtils.escapeFieldNames("areas", "r&d"), EscapeUtils.escapeFieldNames("costs", "price.usd")));
Document newDocument =
new Document()
.append(
"areas",
Map.of(
"r&d", false,
"design", true))
.append(
"costs",
Map.of(
"price.usd", 100,
"price.cad", 90));
Optional<Document> result = collection.findOneAndReplace(filter, newDocument, options);
System.out.println(result);
}
}
curl -sS -L -X POST "API_ENDPOINT/api/json/v1/KEYSPACE_NAME/COLLECTION_NAME" \
--header "Token: APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"findOneAndReplace": {
"filter": {"$and": [
{"areas.r&&d": false},
{"costs.price&.usd": {"$lt": 300}}
]},
"replacement": {
"areas": {
"r&d": false,
"design": true
},
"costs": {
"price.usd": 100,
"price.cad": 90
}
},
"projection": {"areas.r&&d": true, "costs.price&.usd": true},
"sort": {
"areas.r&&d": 1,
"costs.price&.usd": -1
}
}
}'