...
we need to search over data across multiple anchors for a given dataspace. for this requirement below changes are proposed
Issues & Decisions
# | Issue | Notes | Decision |
---|
1 | Exact |
---|
respons response format | would like to be able to determine which |
dat data is from which anchor See |
3 2 alternatives below |
|
2 | include-descendants | should we use 'include-descendants' (true | false) in query parameter as we have in V1 or do we need to use 'descendants' in query parameter as in V2 |
|
---|
Endpoint Definition
New endpoint : GET http://localhost:8883/cps/api/v2/dataspaces/{dataspace-name}/nodes/query
...
# | scenario | Body Structures | Response Body Example |
---|
1 | without anchor name | [{data-tree1},..,{data-tree-n}] | Code Block |
---|
language | xml |
---|
title | Example |
---|
collapse | true |
---|
|
[
{
"test:bookstore": {
"bookstore-name": "Chapters",
"categories": [
{
"code": 1,
"name": "SciFi"
},
{
"code": 2,
"name": "kids"
}
]
}
},
{
"test:bookstore2": {
"bookstore-name": "Chapters2",
"categories": [
{
"code": 10,
"name": "SciFi"
},
{
"code": 20,
"name": "kids"
}
]
}
}
] |
2 | anchor name per data node | [{data-tree1},..,{data-tree-n}] |
Code Block |
---|
language | xml |
---|
title | example |
---|
collapse | true |
---|
| [
{
"test:bookstore": {
"bookstore-name": "Chapters",
"categories": [
{
"code": 1,
"name": "SciFi"
},
{
"code": 2,
"name": "kids"
}
]
},
"anchorName": "anchor01"
},
{
"test:bookstore2": {
"bookstore-name": "Chapters2",
"categories": [
{
"code": 10,
"name": "SciFi"
},
{
"code": 20,
"name": "kids"
}
]
},
"anchorName": "anchor02"
}
] |
|
32 | list of data nodes per anchor | [ {"anchorName":"anchor-01", "dataNodes":[{data-tree1},...{data-tree-n}] ... ,{"anchorName":"anchor-02", "dataNodes": [{datatree1},...,{data-tree-n}] } ] |
Code Block |
---|
language | xml |
---|
title | example |
---|
collapse | true |
---|
| [
{
"anchorName":"anchor01",
"dataNodes":[
{
"test:bookstore":{
"bookstore-name":"Chapters",
"categories":[
{
"code":1,
"name":"SciFi"
}
]
}
}
]
},
{
"anchorName":"anchor02",
"dataNodes":[
{
"test:bookstore":{
"bookstore-name":"store01",
"categories":[
{
"code":2,
"name":"SciFi"
}
]
}
}
]
}
] |
|
...
file |
|
---|
openapi.yml | add new endpoint: Code Block |
---|
language | java |
---|
title | New endpoint |
---|
collapse | true |
---|
| /v2/dataspaces/{dataspace-name}/nodes/query:
$ref: 'cpsQueryV2.yml#/nodesByDataspaceAndCpsPath' |
|
cpsQueryV2.yml |
Code Block |
---|
language | xml |
---|
title | cpsQueryV2.yml |
---|
linenumbers | true |
---|
collapse | true |
---|
| nodesByDataspaceAndCpsPath:
get:
description: Query data nodes for all anchors of a given dataspace using CPS path
tags:
- cps-query
summary: Query data nodes across all anchors
operationId: getNodesByDataspaceAndCpsPath
parameters:
- $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
- $ref: 'components.yml#/components/parameters/cpsPathInQuery'
- $ref: 'components.yml#/components/parameters/descendantsInQuery'
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
examples:
dataSample:
$ref: 'components.yml#/components/examples/dataSample'
'400':
$ref: 'components.yml#/components/responses/BadRequest'
'401':
$ref: 'components.yml#/components/responses/Unauthorized'
'403':
$ref: 'components.yml#/components/responses/Forbidden'
'500':
$ref: 'components.yml#/components/responses/InternalServerError'
x-codegen-request-body-name: xpath |
|
FragmentRepositoryCpsPathQueryImpl.java |
Code Block |
---|
language | java |
---|
title | FragmentRepositoryCpsPathQueryImpl.java |
---|
linenumbers | true |
---|
collapse | true |
---|
| @Override
@Transactional
public List<FragmentEntity> findByCpsPath(final CpsPathQuery cpsPathQuery) {
final StringBuilder sqlStringBuilder = new StringBuilder("SELECT * FROM FRAGMENT");
final Map<String, Object> queryParameters = new HashMap<>();
sqlStringBuilder.append(" WHERE xpath ~ :xpathRegex");
final String xpathRegex = getXpathSqlRegex(cpsPathQuery);
queryParameters.put("xpathRegex", xpathRegex);
if (cpsPathQuery.hasLeafConditions()) {
sqlStringBuilder.append(" AND attributes @> :leafDataAsJson\\:\\:jsonb");
queryParameters.put("leafDataAsJson", jsonObjectMapper.asJsonString(
cpsPathQuery.getLeavesData()));
}
addTextFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
final Query query = entityManager.createNativeQuery(sqlStringBuilder.toString(), FragmentEntity.class);
setQueryParameters(query, queryParameters);
final List<FragmentEntity> fragmentEntities = query.getResultList();
log.debug("Fetched {} fragment entities by anchor and cps path.", fragmentEntities.size());
return fragmentEntities;
} |
|
...