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.authentication import UsernamePasswordTokenProvider
from astrapy.constants import Environment
from astrapy import DataAPIClient
from astrapy.constants import SortMode
# Get an existing collection
client = DataAPIClient(environment=Environment.HCD)
database = client.get_database(
"API_ENDPOINT",
token=UsernamePasswordTokenProvider("USERNAME", "PASSWORD"),
)
collection = database.get_collection("COLLECTION_NAME", keyspace="KEYSPACE_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.authentication import UsernamePasswordTokenProvider
from astrapy.constants import Environment
from astrapy import DataAPIClient
from astrapy.constants import SortMode
from astrapy.utils.document_paths import escape_field_names
# Get an existing collection
client = DataAPIClient(environment=Environment.HCD)
database = client.get_database(
"API_ENDPOINT",
token=UsernamePasswordTokenProvider("USERNAME", "PASSWORD"),
)
collection = database.get_collection("COLLECTION_NAME", keyspace="KEYSPACE_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, UsernamePasswordTokenProvider} from "@datastax/astra-db-ts";
// Get an existing collection
const client = new DataAPIClient({ environment: "hcd" });
const database = client.db("API_ENDPOINT", {
token: new UsernamePasswordTokenProvider("USERNAME", "PASSWORD"),
});
const collection = database.collection("COLLECTION_NAME", {
keyspace: "KEYSPACE_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, UsernamePasswordTokenProvider, escapeFieldNames } from "@datastax/astra-db-ts";
// Get an existing collection
const client = new DataAPIClient({ environment: "hcd" });
const database = client.db("API_ENDPOINT", {
token: new UsernamePasswordTokenProvider("USERNAME", "PASSWORD"),
});
const collection = database.collection("COLLECTION_NAME", {
keyspace: "KEYSPACE_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.DataAPIClients;
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 =
DataAPIClients.clientHCD("USERNAME", "PASSWORD")
.getDatabase("API_ENDPOINT", "KEYSPACE_NAME")
.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.DataAPIClients;
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 =
DataAPIClients.clientHCD("USERNAME", "PASSWORD")
.getDatabase("API_ENDPOINT", "KEYSPACE_NAME")
.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/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
}
}
}'