Versions Compared

Key

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

...

Table of Contents

Issues & Decisions

NotesDecisions

 

  • As per discussion with Lukasz Rajewski the following decisions were made:
    • The approach to have a custom logic to retrieve all the list items seems to be most appropriate to make Get Data Node API consistent with Query API
    • The approach to use a special character, asterisk(*) does not address the problem of inconsistency. As we would like to have the xpath in request consistent with that in Query API
      • Example: 

        Code Block
        /v2/dataspaces/my-dataspace/anchors/multipleTop/node?xpath=/bookstore/categories&descendants=3


    • The approach to Redirect the request to Query API does not seem to be a feasible approach.
03 Mar

 

After discussion in the CPS-sub team, following conclusions were made:

  • Use correct Error Code and Response Message, when updating multiple data nodes
  • As per CPS Exceptions and REST APIs HTTP Response Codes, the response code was set to 400 with appropriate message.
  • Update for single data node with root node xpath remains as it is.

Inconsistent response when retrieving data nodes.

More research needs to be done for the first proposed approach and need to document it in detail.

 

As per discussion with Daniel Hanrahan and Lee Anjella Macabuhay it was decided to change the Query for retrieveing the data nodes such that it can get all data nodes that fall under a given list. The query change is based on an internal PoC prepared by Daniel through which we can retrieve all the list items by specifying the xpath of list without impacting the performance.

Change the Query to retrieve all the list items under a given list using its xPath

Inconsistent response when retrieving data nodes.

When a get When a get operation is performed on Root node xpath (/) it returns an array list containing all the data nodes under the root node xpath. But if the same operation is performed for a List Data node no array list is returned instead a 404 Not Found response is returned.

...

Note: The problem with this approach is to identify whether the request data node is a list or not, by using the xpath provided in the Get request. Also it is not feasible to redirect the request to Query API.

Accepted Solution

By modifying the SQL query to retrieve the data nodes we can fetch all the list items which have a similar xpaths.

In the present query, when querying a list item, we specify its absolute xpath as it is the only available data node with the specified xpath. Ex: /bookstore/categories[@code="1"]

When we try to query the entire list, we get DataNodeNotFound exception because there is no data node with the xpath representing a list in the database. Ex: /bookstore/categories

"id""xpath""attributes"

"parent_id"

200"/bookstore/categories[@book-category='Kids']""{""name"": ""Kids book"", ""price"": 5000, ""stock"": true, ""book-category"": ""Kids""}"

198

199"/bookstore/categories[@book-category='SciFi']""{""name"": ""Test book"", ""price"": 1000, ""stock"": false, ""book-category"": ""SciFi""}"198
198"/bookstore""{""store-name"": ""My Bookstore"", ""store-owner"": ""ABC""}"null


Code Block
titleSegment from the Old query to match the xpath
WHERE anchor_id = :anchorId AND xpath = ANY (:xpaths)

So, from the above snapshot of the fragment table, it can be clearly seen that individual list items are stored in the CPS DB and there is no data node representing the entire list. And hence when the existing query is executed it looks for the fragment with the specific xpath. 

Now, the updated query does not look for a list data node for a given xpath (representing a list Ex: /bookstore/categories). Instead, it looks for all the fragments in the table which have a similar xpath starting with "[" and ending with ] using pattern matching.

To make it work we use a combination of LIKE and NOT LIKE keywords.

For this we make use of the LIKE keyword along with % wildcard to make use of pattern matching.

But the above query would also return fragments for xpaths like /bookstore/categories[@code='1']/books[@name="Hello"]

To avoid this scenario, we make use of NOT LIKE keyword along with the same % wildcard. and hence we have [%[% to exclude multiple opening brackets.

Code Block
titleUpdated Query
"SELECT * FROM fragment WHERE anchor_id = :anchorId "
            + "AND xpath LIKE :escapedXpath||'[@%]' ESCAPE '\\' "
            + "AND xpath NOT LIKE :escapedXpath||'[@%[%' ESCAPE '\\'"

And this would return 2 fragments as follows.

"id""xpath""attributes"

"parent_id"

200"/bookstore/categories[@book-category='Kids']""{""name"": ""Kids book"", ""price"": 5000, ""stock"": true, ""book-category"": ""Kids""}"

198

199"/bookstore/categories[@book-category='SciFi']""{""name"": ""Test book"", ""price"": 1000, ""stock"": false, ""book-category"": ""SciFi""}"198

Impact on response body

The updated query returns child fragments when querying the entire list and it has the following impacts when compared to the existing response body.

Currently in order to retrieve the entire list data node we have to query the Parent data node. So, in the above example for the list named "categories" we have to query the parent node that is "bookstore". Hence the xpath in the query would become "/bookstore" and we would get the following response:

Code Block
titleCurrent Response
collapsetrue
[
    {
        "stores:bookstore": {
		 	"store-name": "My Bookstore",
            "store-owner": "ABC",
            "categories": [
                {
                    "name": "Test book",
                    "price": 1000,
                    "stock": false,
                    "book-category": "SciFi"
                },
                {
                    "name": "Kids book",
                    "price": 5000,
                    "stock": true,
                    "book-category": "Kids"
                }
            ]
        }
    }
]

Here we can see that in the response we get a parent node bookstore and the list named "categories", as its child, and the list items identified by keys "SciFi" and "Kids" respectively. 

But when we query the entire list directly using the updated query we will get 2 data nodes (representing "SciFi" and "Kids") instead of one parent node ("bookstore") with 2 children ("SciFi" and "Kids"). 

These 2 individual data nodes when parsed into a JSON will result in a response with as follows:

Code Block
titleResponse when retrieving whole list
collapsetrue
[
    {
        "stores:categories": {
            "name": "Test book",
            "price": 1000,
            "stock": false,
            "book-category": "SciFi"
        }
    },
    {
        "stores:categories": {
            "name": "Kids book updated",
            "price": 5000,
            "stock": true,
            "book-category": "Kids"
        }
    }
]

The behavior is consistent with the existing functionality of Query API as well:

Code Block
titleResponse with Query API
collapsetrue
[
    {
        "stores:categories": {
            "name": "Test book",
            "price": 1000,
            "stock": false,
            "book-category": "SciFi"
        }
    },
    {
        "stores:categories": {
            "name": "Kids book updated",
            "price": 5000,
            "stock": true,
            "book-category": "Kids"
        }
    }
]