Skip to content
25 changes: 22 additions & 3 deletions java/cds-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ The [predefined CDS types](../cds/types) are mapped to Java types and as follows
| `cds.Binary` | `byte[]` | |
| `cds.LargeBinary` | `byte[]` | `java.io.InputStream` <sup>(1)</sup> if annotated with `@Core.MediaType` |
| `cds.Vector` | `com.sap.cds.CdsVector` | for [vector embeddings](#vector-embeddings) |
| `cds.Map` | `java.util.Map` | for arbitrary [structured data](#structured-data)<sup>(2)</sup> |
| `cds.Map` | `java.util.Map` | for schemaless [structured data](#cds-map) |

### SAP HANA-Specific Data Types

Expand All @@ -63,7 +63,6 @@ To facilitate using legacy CDS models, the following [SAP HANA-specific data typ


> <sup>(1)</sup> Although the API to handle large objects is the same for every database, the streaming feature, however, is supported (and tested) in **SAP HANA**, **PostgreSQL**, and **H2**. See section [Database Support in Java](./cqn-services/persistence-services#database-support) for more details on database support and limitations.
> <sup>(2)</sup> Serialized as JSON to a CLOB column or JSONB column (on Postgres)

::: warning
The framework isn't responsible for closing the stream when writing to the database. You decide when the stream is to be closed. If you forget to close the stream, the open stream can lead to a memory leak.
Expand All @@ -74,7 +73,7 @@ These types are used for the values of CDS elements with primitive type. In the
## Structured Data

In CDS, structured data is used as payload of *Insert*, *Update*, and *Upsert* statements. Also the query result of *Select* may be structured.
CAP Java represents data of entities and structured types as `Map<String, Object>` and provides the `CdsData` interface as an extension of `Map` with additional convenience methods.
CAP Java represents data of entities, structured types and elements of type [cds.Map](#cds-map) as `java.util.Map<String, Object>` and provides the `CdsData` interface as an extension of `Map` with additional convenience methods.

In the following we use this CDS model:

Expand Down Expand Up @@ -279,6 +278,26 @@ Avoid cyclic relationships between CdsData objects when using toJson.

<div id="cdsdata-serialization-jsonconverter"/>

## Map Data<Beta /> { #cds-map }

Elements of type `cds.Map` can be used to store arbitrary _schemaless_ [stuctured data](#structured-data). CAP Java represents data of elements of type `cds.Map` as `Map<String, Object>`.

On the database, this data is serialized to [JSON](https://www.json.org/)<sup>(2)</sup>. Only data types that are compatible with JSON can be stored and retrieved:

| Java Type | JSON Type |
| ---------------------------------| --------------- |
| `java.lang.String` | `string` |
| `java.lang.Number`<sup>(2)</sup> | `number` |
| `java.lang.Boolean` | `true`, `false` |
| `java.util.Map` | `object` |
| `java.util.List` | `array` |
| `null` | `null` |

> <sup>(1)</sup> Serialized as JSON to a CLOB column or JSONB column (on Postgres)

> <sup>(2)</sup> The actual subclass of a `Number` is not preserved upon serialization and might change upon deserialization.

Map data can be nested and may contain `List`s, which are serialized to JSON arrays.

## Vector Embeddings <Beta /> { #vector-embeddings }

Expand Down
78 changes: 78 additions & 0 deletions java/working-with-cql/query-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,30 @@ Select.from(BOOKS)
Select.from(BOOKS).byParams("title", "author.name");
```

#### Filtering Map Data<Beta />

You can also filter by _content_ of [map data](../cds-data.md#cds-map) (i.e. elements of type `cds.Map`). Considering this model

```cds
entity Product : cuid {
name : String;
category : String;
details : Map;
}
```

the following query selects all products of the category "tech" and where type Map element `details` contains a sub-element `brand` with the value "ACME":

```java
Select.from(PRODUCTS)
.where(p -> p.category().eq("tech").and(
p.to("details").get("brand").eq("ACME")));
```

::: warning
Depending on the data database, filtering by content of map data can be an expensive operation. A filter by a content of map data should only be used to make a filter that uses column data more restrictive.
:::

### Parameters

The [CQL](../../cds/cql) builders support [parameters](#expr-param) in the `where` clause and in infix filters for [parameterized execution](query-execution#parameterized-execution):
Expand Down Expand Up @@ -536,6 +560,34 @@ Object authorId = book.get("author.Id"); // path access
Only to-one associations that are mapped via the primary key elements of the target entity are supported on the select list. The execution is optimized and gives no guarantee that the target entity exists, if this is required use expand or enable [integrity constraints](../../guides/databases#database-constraints) on the database.
:::

#### Selecting Map Data <Beta />

You can also use elements of type [cds.Map](../cds-data.md#cds-map) on the select list. Considering this model

```cds
entity Product : cuid {
name : String;
category : String;
details : Map;
}
```

the query

```java
Select.from(PRODUCTS).columns(p -> p.ID(), p.details());
```

will select the product's ID along with the details, which are returned as a `Map<String, Object>`. You can also select sub-elements of elements of type `cds.Map`:

```java
Select.from(PRODUCTS)
.columns(p-> p.ID(),
p-> p.to("details").get("brand"))
.where(p -> p.category().eq("tech"));
```

This query selects the sub-element `brand` of the element `details` for all products of category "tech".

### Filtering and Searching { #filtering}

Expand All @@ -556,6 +608,7 @@ entity Book {
title : String;
}
```

In the following example, element `title` is included in `@cds.search`. Only this particular element is searchable then.

```cds
Expand Down Expand Up @@ -817,6 +870,31 @@ In this example, it's assumed that the total number of books is more or equal to
The pagination isn't stateful. If rows are inserted or removed before a subsequent page is requested, the next page could contain rows that were already contained in a previous page or rows could be skipped.
:::

#### Sorting by Map Data<Beta />

You can also sort by _content_ of [map data](../cds-data.md#cds-map) (i.e. elements of type `cds.Map`). Considering this model

```cds
entity Product : cuid {
name : String;
category : String;
details : Map;
}
```

this query sorts products by category and additionally by the sub-element `brand` of the map element `details`.

```java
Select.from(PRODUCTS)
.where(p -> p.category().eq("tech"))
.orderBy(p -> p.category().asc(),
p.to("details").get("brand").asc());
```

::: warning
Depending on the data database, sorting by content of map data can be an expensive operation and should only be applied on a small result set.
:::

### Pessimistic Locking { #write-lock}

Use the `lock()` method to enforce [Pessimistic Locking](../../guides/providing-services#select-for-update).
Expand Down
Loading