Jira Ref:
Jira |
---|
server | ONAP Jira |
---|
columnIds | issuekey,summary,issuetype,created,updated,duedate,assignee,reporter,priority,status,resolution |
---|
columns | key,summary,type,created,updated,due,assignee,reporter,priority,status,resolution |
---|
serverId | 425b2b0a-557c-3c0c-b515-579789cceedb |
---|
key | CPS-1377 |
---|
|
Requirement :
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 response format | would like to be able to determine which data is from which anchor See 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
parameters:
parameter name | in | isRequired |
---|
dataspace-name | path | yes |
cps-path | query | yes |
...
Response Definition
we can have below responses
response body | Decision | without anchor name | [{ "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" } ] }}] | Body Structures | Response Body Example |
---|
1 | anchor name per data node | [{data-tree1},..,{data-tree-n}] |
Code Block |
---|
language | xml |
---|
title | example |
---|
collapse | true |
---|
| [
{
|
|
anchor name per data node | [{
"bookstore-name": "Chapters", |
|
"bookstore-name": "Chapters2", |
|
] |
2 | list of data nodes per anchor |
{"anchor01": 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" } ] }}],"anchor02": [{ "test:bookstore": { {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", |
|
{ }, { "code": 2, "name": "kids" } ] }},{ "test:bookstore2": {
}
]
}
}
]
},
{
"anchorName":"anchor02",
"dataNodes":[
{
"test:bookstore":{
"bookstore-name":" |
|
Chapters2", { 10, }, { "code": 20, "name": "kids" } ] }}]}...
Required Code Changes
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: |
|
|
description: Query data nodes for all anchors of a given dataspace using CPS path |
|
|
|
summary: Query data nodes across all anchors |
|
operationId: getNodesByDataspaceAndCpsPath |
|
|
- $ref: 'components.yml#/components/parameters/dataspaceNameInPath' |
|
- $ref: 'components.yml#/components/parameters/cpsPathInQuery' |
|
- $ref: 'components.yml#/components/parameters/descendantsInQuery' |
|
|
|
|
|
|
|
|
|
|
$ref: 'components.yml#/components/examples/dataSample' |
|
|
$ref: 'components.yml#/components/responses/BadRequest' |
|
|
$ref: 'components.yml#/components/responses/Unauthorized' |
|
|
$ref: 'components.yml#/components/responses/Forbidden' |
|
|
$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 |
|
|
| List<FragmentEntity>List<FragmentEntity> findByCpsPath(final CpsPathQuery cpsPathQuery) { |
|
final StringBuilder sqlStringBuilder = new StringBuilder("SELECT * FROM FRAGMENT"); |
|
| Map<String | Object>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); |
|
| List<FragmentEntity>List<FragmentEntity> fragmentEntities = query.getResultList(); |
|
log.debug("Fetched {} fragment entities by anchor and cps path.", fragmentEntities.size()); |
|
|
|