Standard REST Api convention while updating child resource - json

I have a situation : Category - Master data with different types.
Order - Has a reference to Category.
It is a one-to-one mapping from Order to Category. Order table has a foreign key column to Category.
Now api to get Orders
/users/orders
Will the return type as
{ "name: "abc", "categoryId" : 23 }
will be fine or should we return the json as
{ "name: "abc", "category" : "CAT-A" }
We also have a create/update Order use case with client knowing the category.
We need a api to post new Order with a Category.
Should it be something like this?
1. post /api/orders { "categoryId" : 23, ....}
Or something like this?
2. post /api/orders/category/23/order

first, use identifiers (or links!):
{ "name: "abc", "categoryId" : 23 }
or
{ "name: "abc", "category" : "/api/categories/23" }
not names (because those could change from time to time)
{ "name: "abc", "category" : "CAT-A" }
For the posting of orders I would suggest to use
post /api/orders { "categoryId" : 23, ....}
just because you are adding an order on the order resource. The order should already have a category referenced (or linked!).
This approach
post /api/orders/category/23/order
would also be okay. But the client would need to build an url with information that is already contained in the request body, so things only got a little more complicated (what if the categories in url and request body are not the same? What if the category in the request body is missing? Is the request still valid in this case?)

Related

Goessner JSON Query Syntax and Filtering

Looking to filter this json body for specific key/values for when a certain condition is met.
For this body - I'd like to retrieve ONLY the recipient ID and Tracking Number for when the requester ID is 67890.
{
"metadata": "someinformation",
"access": "XXXX",
"recipient": {
"id": "12345"
},
"requester": {
"id": "67890"
},
"trackingNumber": "ABCDEF"
}
This would be using Goessner https://goessner.net/articles/JsonPath/index.html
I am able to get the attributes mostly using: $..[trackingNumber,requester,recipient] but it removes the key of "trackingNumber" and only does a value.
Also the filter I want to use alongside that would be: [?($.requester.id=="67890")]
The expectation is other requester ID's will be in other json bodies - but we only want to filter for the ones that have this present and select the specific attributes.
You going to need to do this in two queries, one for each value that you want back.
For recipient:
$[?(#.requester.id == '67890')].recipient.id
For tracking number:
$[?(#.requester.id == '67890')].trackingNumber
I don't think Goessner's implementation supports returning multiple values like you want. It's not something that will be supported in the upcoming spec, either.

REST POST json body to support complex query advice

I'm fairly new to REST. All of our legacy webservices were SOAP based with enterprise (ORACLE or DB2) databases. We are now moving to REST/couchbase.
Our team is looking into implementing a complex query method. We already have implemented simple query methods using GET, for example GET returns all entries and a GET/067e6162-3b6f-4ae2-a171-2470b63dff00 would return the entry for 067e6162-3b6f-4ae2-a171-2470b63dff00.
We want to support a query method that would support receiving several query parameters such a list of Ids and date ranges. The number of Ids can number into a few thousand and because of this, we realize we cannot pass these query parameters in a GET HTTP header since there is a limit on header size.
We are starting to look into passing our query parameters into the JSON body of a POST request. For example, we could have client pass in a few thousand Ids as an array and also pass in a date range, so we'd have each query param/filter be an object. The JSON body would then be an array of objects. For example:
{
"action" : "search",
"queryParameters" : {
[
{
“operation”: “in”,
"key" : "name.of.attribute.Id",
"value" : "[{ "id: "067e6162-3b6f-4ae2-a171-2470b63dff00"}, {"id": "next id"....}],
},
{
“operation”: “greater”,
"key" : "name.of.attribute “,
"value" : "8/20/2016"
},
{
“operation”: “less”,
"key" : "name.of.attribute “,
"value" : "8/31/2016"
}
]
}
The back end code would then receive POST and read the body. It would see action is a search and then look for any entries in the list that are in the list of Ids that are in the date range of > 8/20/2016 and < 8/31/2016.
I've been trying to look online for tips/best practices on how best to structure the JSON body for complex queries but have not found much. So any tips, guidance or advice would be greatly appreciated.
thanks.

Join documents in Couchbase view

Noob Question on Couchbase / NOSQL :
I have 2 different types of documents which have a common field across them, I would like to join them using views based on that common field :
Document 1 - Key : Page_Object1
{
"URL": "/someurl/",
"title": "some title"
}
Document 2 Key : Zone_Object1
{
"URL": "/someurl/",
"zone": "some Ad zone"
"
}
Can someone pls help me join these 2 documents and return a single joined document (using view?) based off of the "url" field, both these documents live in the same bucket.
Actually, I guess the view code posted will not work.
The correct would be:
if (doc.title) {
emit (doc.url, doc.title)
} else if (doc.zone) {
emit (doc.url, doc.zone)
}
And it's true,
If you have N1QL available, you'll get a proper join mechanism.
According to the Couchbase documentation http://docs.couchbase.com/admin/admin/Views/views-querySample.html, this is not possible in the strict sense.
But you can define your view like
if (doc.type == "page") {
emit (doc.url, doc.title)
} else if (doc.type == "zone") {
emit (doc.url, doc.zone)
}
Now, when querying this view for a given url, you'll get both informations.
If you have N1QL available, you'll get a proper join mechanism.

Limiting and sorting by different properties on couchbase

Given a JSON document on couchbase, for example, a milestone collections, which is similar to this:
{
"milestoneDate" : /Date(1335191824495+0100)/,
"companyId" : 43,
"ownerUserId": 475,
"participants" : [
{
"userId": 2,
"docId" : "132546"
},
{
"userId": 67,
"docId" : "153"
}
]
}
If I were to select all the milestones of the company 43 and want to order them by latest first.. my view on couchbase would be something similar to this:
function (doc, meta) {
if(doc.companyId && doc.milestoneDate)
{
//key made up of date particles + company id
var eventKey = dateToArray(new Date(parseInt(doc.milestoneDate.substr(6))));
eventKey.push(doc.companyId);
emit(eventKey, null);
}
}
I do get both dates and the company Id on rest urls.. however, being quite new to couchbase, I am unable to work out how to restrict the view to return only milestones of company 43
The return key is similar to this:
"key":[2013,6,19,16,11,25,14]
where the last element (14) is the company id.. which is quite obviously wrong.
The query parameters that I have tried are:
&descending=true&startkey=[{},43]
&descending=true&startkey=[{},43]&endKey=[{},43]
tried adding companyId to value but couldn't restrict return results by value.
And according to couchbase documentation I need the date parts in the beginning to sort them. How do I restrict them by company id now, please?
thanks.
Put the company id at the start of the array, and because you'll be limiting by company id, couchbase sorts by company id and then by date array so you will be only ever getting the one company's milestone documents
I'd modify the view to emit
emit([doc.copmanyId, eventKey], null);
and then you can query the view with
&descending=true&startkey=[43,{}]
This was what worked for me previously..
I went back and tried it with end key and this seems to work - restricts and orders as required:
&descending=true&startkey=[43,{}]&endkey=[42,{}]
or
&descending=true&startkey=[43,{}]&endkey=[43,{}]&inclusive_end=true
either specify the next incremented/decremented value (based on descending flag) with end key, or use the same endkey as startkey and set inclusiveEnd to true
Both of these options should work fine. (I only tested the one with endkey=42 but they should both work)

mongodb find() order is different from schema order

db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})
what should below return as the key order does not match?
db.blog.find({"author" : {"id" : 1, "name" : "Jane"}})
EDIT:
based on official mongodb documentation , the keyorder must match (at least for findOne()). It wont return the match-only object using db.blog.findOne({"author" : {"id" : 1, "name" : "Jane"}})
The order of the keys in your query selector is irrelevant. It doesn't need to match the order of the keys you used when adding the document you're searching for.
UPDATE
If you're just looking for an order-independent way to query based on an embedded document, you need to use dot notation:
db.blog.find({"author.id" : 1, "author.name" : "Jane"})
Normally, as #JohnnyHK states the order of the query keys does not matter except for the example you have shown:
db.blog.find({"author" : {"id" : 1, "name" : "Jane"}})
This query will not return results that do not match exactly. Using the query he shows of:
db.blog.find({"author.id" : 1, "author.name" : "Jane"})
Will be key order independent. The reasons for this difference is because in the first query you are searching by an object as such the querier actually searches for exactly that object (in the simplest terms). The same applies for indexes created on the field which contains a set of sub documents, the order does matter.
According to the JSON definition, the key order doesn't matter.
An object is an unordered collection of zero or more name/value pairs
I don't know anything about MongoDB, but I assume it follows the normal rules of JSON, at which point it should return the "My First Post" entry.