Versions Compared

Key

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

...

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
titleOld query
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 to that of the list followed by opening square bracket "[" and any attribute identified in the query by special symbol "%"

Code Block
titleUpdated Query
WHERE anchor_id = :anchorId "
+ "     AND (xpath = ANY (:xpaths) OR xpath LIKE ANY (array(SELECT concat(t, '[%') FROM unnest(:xpaths) as t)))

So as seen in the above segment of the query, we have "AND (xpath = ANY (:xpaths) OR xpath LIKE ANY (array(SELECT concat(t, '[%') FROM unnest(:xpaths) as t)))".

Any given xpath for a list (Ex: /bookstore/categories) would become like so:

Code Block
(xpath = '/bookstore/categories' OR xpath LIKE '/bookstore/categories[%')

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
[
    {
        "stores:bookstore": {
            "categories": [
                {
                    "name": "Test book",
                    "price": 1000,
                    "stock": false,
                    "book-category": "SciFi"
                },
                {
                    "name": "Kids book",
                    "price": 5000,
                    "stock": true,
                    "book-category": "Kids"
                }
            ],
			"store-name": "My Bookstore",
            "store-owner": "ABC"
        }
    }
]

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
[
    {
        "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
[
    {
        "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"
        }
    }
]