Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

we need to search over data across multiple anchors for a given dataspace. for this requirement below changes are proposed 

Issues & Decisions

#IssueNotes Decision
1Exact
respons
response  format

would like to be able to determine which

dat

data is from which anchor

See

3 alternatives below

2 alternatives below


2include-descendantsshould 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

...

without Example[
{
 






























#scenarioBody StructuresResponse Body Example
1anchor name per data node[{data-tree1},..,{data-tree-n}]


Code Block
languagexml
title
example
collapsetrue
2anchor name per data node
[
{
  "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"

}

]


32list of data nodes per anchor {
"anchor01":

[

{


 

"

test:bookstore

anchorName":

{
   

"

bookstore

anchor-

name

01"

: "Chapters"

,

   

"

categories

dataNodes":[


      {
        "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
languagexml
titleexample
collapsetrue
[
   {
      "anchorName":"anchor01",
      "dataNodes":[
         {
            "test:bookstore":{
               "bookstore-name":"Chapters",

   

               "categories":[

      {
       

                  {
                     "code":1,

       

                     "name":"SciFi"

      },
      {
        "code": 2,
        "name": "kids"
      }
    ]
  }
},
{
  "test:bookstore2": {
   

                  }
               ]
            }
         }
      ]
   },
   {
      "anchorName":"anchor02",
      "dataNodes":[
         {
            "test:bookstore":{
               "bookstore-name":"
Chapters2",
   
store01",
               "categories":[

      {
       

                  {
                     "code":
10,
       
2,
                     "name":"SciFi"

      },
      {
        "code": 20,
        "name": "kids"
      }
    ]
  }
}
]
}

                  }
               ]
            }
         }
      ]
   }
]


Required Code Changes






























@Override
@Transactional
public List<FragmentEntity>

Map<StringObject>











List<FragmentEntity>


file
openapi.yml

add new endpoint:

Code Block
languagejava
titleNew endpoint
collapsetrue
/v2/dataspaces/{dataspace-name}/nodes/query:
  $ref: 'cpsQueryV2.yml#/nodesByDataspaceAndCpsPath'

cpsQueryV2.yml


Code Block
languagexml
titlecpsQueryV2.yml
linenumberstrue
collapsetrue
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
languagejava
titleFragmentRepositoryCpsPathQueryImpl.java
linenumberstrue
collapsetrue
@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;

}