REST related/nested objects URL standard - rest

if /wallet returns a list a wallets and each wallet has a list of transactions. What is the standard OpenAPI/REST standard?
For example,
http://localhost:8000/api/wallets/ gives me
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"user": 1,
"address": "3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd",
"balance": "2627199.00000000"
}
]
}
http://localhost:8000/api/wallets/3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd/ gives me
{
"user": 1,
"address": "3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd",
"balance": "2627199.00000000"
}
If I wanted to add a transactions list, what is the standard way to form this?
http://localhost:8000/api/wallets/3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd/transactions ?
http://localhost:8000/api/wallets/3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd/transactions?offset=100 for pagination

REST doesn't care what spelling conventions you use for your resources. What it would instead expect is that you have representations of links between resources, along with meta data describing the nature of the link.
So this schema is fine.
/api/wallets/3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd
/api/wallets/3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd/transactions
And this schema is also fine.
/api/wallets/3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd
/api/transactions/3E8ociqZa9mZUSwGdSmAEMAoAxBK3FNDcd
As far as I can tell, OpenAPI also gives you the freedom to design your resource model the way that works best for you (it just tells you one possible way to document the resource model you have selected).

Related

MongoDB search multiple Field in multiple subDocument

My MongoDB data structure looks like this:
{
"id": "7118592",
"passages": [
{
"infons": {
"article-id_pmid": "32292259",
"title": "Keywords",
"type": "front",
"section_type": "TITLE"
},
"text": "Understanding of guidance for acupuncture and moxibustion interventions on COVID-19 (Second edition) issued by CAAM"
},
{
"infons": {
"section_type": "ABSTRACT",
"type": "abstract",
"section": "Abstract"
},
"offset": 116,
"text": "At present, the situation of global fight against COVID-19 is serious. WHO (World Health Organization)-China Joint Mission fully confirms the success of \"China's model\" against COVID-19 in the report. In fact, one particular power in \"China's model\" is acupuncture and moxibustion of traditional Chinese medicine. To better apply \"non-pharmaceutic measures\":the external technique of traditional Chinese medicine, in the article, the main content of Guidance for acupuncture and moxibustion interventions on COVID-19 (Second edition) issued by China Association of Acupuncture-Moxibution is introduced and the discussion is stressed on the selection of moxibustion device and the duration of its exertion."
}
]
}
I want to request the article-id_pmid and the text in the same subdocument, also the text of subdocument which contains in infons a field with section_type : ABSTRACT and type: abstract.
I had tried this request but the result was not what I am searching for:
db.mydata.find({$and:[{"passages.infons.article-id_pmid$":{$exists: true}},{"passages.infons.section_type":"ABSTRACT"},{"passages.infons.type":"abstract"}]},{"passages.infons.article-id_pmid.$":1,_id:0, "passages.text":1})
Each of the top-level conditions is treated independently.
Use https://docs.mongodb.com/manual/reference/operator/query/elemMatch/ to specify multiple conditions on the same array element.

Partial Representations in REST API's for collections vs items

I'm putting together a REST based API but I'm not sure on how I should deliver the response for collections vs individual resources.
Does it make sense to have a slimmed down representation for a collection over a single item in the world of REST?
Say I have something along the lines of this for a collection of albums:
{
items: [
{
"id": 1,
"title": "Thriller"
},
...
]
}
But then for the actual individual item I had
{
"id": 1,
"title": "Thriller",
"artist": "Michael Jackson",
"released": "1982",
"imageLinks": {
"smallThumbnail": "...",
"largeThumbnail": "..."
}
...
}
A resource representation should be unique irrespective of whether it is given as a collection or a single item. But, you can introduce a new parameter like fields which can be used by the clients to get only the required field thereby optimising the bandwidth.
/albums - This should give the list of objects each having the structure of what you would give in a individual item api
/albums?fields=id,title - This can give the list of objects with just the id & title.

How to query Cloudant documents for a specific field

I am new to Cloudant and I need to do a simple query on a specific document field. My documents have the following structure and I need to get only the documents with status=SIGNED
{
"_id": "3ddb4058f3b24a7a9c585f997e30ff78",
"_rev": "3-757c82c48f4e7c333911be6859aff74e",
"fileName": "Generali Architects",
"status": "SIGNED",
"user": "italy",
"_attachments": {
"Generali Architects": {
"content_type": "application/pdf",
"revpos": 3,
"digest": "md5-9hqSif7CzQ2yvKxSSbj+dw==",
"length": 323653,
"stub": true
}
}
}
Reading Cloudant documentation I created the following Design Document with a related view which returns exactly what I expected
Then from my Java application I use the following code
String cloudantView = "_design/signedDocs/status-signed-iew";
List<SignDocDocument> docs =
db.view(cloudantView).includeDocs(true).query(SignDocDocument.class);
which always returns me "org.lightcouch.NoDocumentException: Object Not Found"
Any idea which kind of mistake I am making here?
Thank you very much
Is it the typo in "_design/signedDocs/status-signed-iew"; e.g. that should be "_design/signedDocs/status-signed-view"; (depending on how your java library works...).
Always worth checking the view by direct access in your browser, too, just to make sure it's returning the expected data.

Is it possible to run a query using Orion where the searching criteria is given by attributes value?

As I create entities in an Orion server, I can search by ID, as flat or using regular expressions:
http://<localhost>:1026/v1/queryContext
Content:
{
"entities": [
{
"type": "Sensor",
"isPattern": "true",
"id": "sensor_1.*"
}
],
"attributes": ["temperature","humidity"]
}
In the above example I'd get all objects of type "Sensor" whose ID starts with "sensor_1", and their attributes "temperature" and "humidity". I wonder if there is any way that would allow me to search by specific attribute value, for example to get those sensors whose humidity is over "60.2", or this selection must be done over the retrieved data queried by ID.
Not in the current Orion version (0.19.0) but it will be possible in the future. Have a look to the attribute::<name> filter with the = operator in this document.

Querying Mongodb for docs which have subobjects with a certain elem value within an associative array

tricky mongodb querying problem: I have a collection 'Accounts' with a bunch of documents that (simplified and with actual data swapped for non-real-world values) look like this:
{"_id": "<Mongo Binary Data>",
"Roles": {
"D7753879C7020F8ECF947122FA211413": {
"_id": "<Mongo Binary Data>",
"OrgName": "ACME",
"Rolename": "Coyote Liaison",
},
"CFA7722E6799170706E4C5FFF3F01E63": {
"_id": "<Mongo Binary Data>",
"OrgName": "ACME",
"Rolename": "MembershipAdmin",
},
"C7020F8ECF947122FAGIGHFVFF3F7753": {
"_id": "<Mongo Binary Data>",
"OrgName": "Initech",
"Rolename": "MembershipAdmin",
}
}
}
The keys in the Roles array are a combination of a role id and an org id which are then hashed, which makes it very quick to query (once an Account object has been loaded up from MongoDB and into C#) for if an Account has a given role for a given org, ie, is a user a MembershipAdmin for Initech.
Now I want to query for users who have a role for ANY org, which in pseudo-SQL could be expressed as 'SELECT all accounts which have at least one role object where Rolename = THISROLENAME'. Ie, get all users which are MembershipAdmins.
I have tried this:
{
Roles.Rolename: "MembershipAdmin"
}
and this
{
Roles: {"Rolename": "MembershipAdmin"}
}
and this
{
Roles: {"$elemMatch": {"Rolename": "MembershipAdmin"}}
}
...to no avail and have seen several answers, etc, saying that the only way out of this is to push the associative array key down into the subobjects, which I don't want to do as it makes the primary function of this data structure (checking if an account has a given role for a given organisation) very quick indeed. The use case I describe above doesn't have to be mega-fast as it is part of an admin user's responsibility so I'm happy to make them wait a few moments - so queries with excessive recursion, etc, are OK in this case.
Does anyone have any ideas how to make this work without refactoring the data structure? At my wit's end with this.
Many thanks,
G
[EDIT: the structure above is not queryable, see the accepted answer for an erudite but quick explanation as to why not and what you should properly do to fix it. If you're OK with a hacky workaround, though, you can store a copy of the data in a BsonArray alongside it and query against that using $elemMatch]
There is no way to do with you want with that schema, nor is the schema very practical to begin with. You should change your schema to this :
{"_id": "<Mongo Binary Data>",
"Roles": [
{
"hash": "D7753879C7020F8ECF947122FA211413",
"_id": "<Mongo Binary Data>",
"OrgName": "ACME",
"Rolename": "Coyote Liaison",
},
{
"hash": "CFA7722E6799170706E4C5FFF3F01E63",
"_id": "<Mongo Binary Data>",
"OrgName": "ACME",
"Rolename": "MembershipAdmin",
},
{
"hash": "C7020F8ECF947122FAGIGHFVFF3F7753",
"_id": "<Mongo Binary Data>",
"OrgName": "Initech",
"Rolename": "MembershipAdmin",
}
]
}
The reason why using nonstable values as document field names is so unpractical is exactly because it complicates most querying. The only upside is that some queries might be a little faster but given the fact that it also causes issues for indexing it's almost always a bad idea.
I would strongly suggest to change your schema to the above rather than look for solutions that allow your current schema.
EDIT: As mentioned in the discussion below it is technically possible to create the needed query using the $where operator. If you cannot do it any other way it means you have a schema smell and a potential scaling and performance bottleneck that will be diabolically hard to fix when your software goes live. Don't use $where. Ever.
[EDIT]: This is wrong. Works if it were an array and not a hash structure. That, anyway was already tried in the question.
Roles.Rolename can be used if there is an index on it.
db.collectionname.ensureIndex({"Roles.Rolename": 1 })
and then,
db.collectionname.find({"Role.Rolename": "MembershipAdmin"})
# returning only the organization field. Not tested though
db.collectionname.find({"Role.Rolename": "MembershipAdmin"},{"Role.Orgname": 1})
Indexing Embedded fields from MongoDB docs has info on it.
Here is how you do it:
db.Accounts.find({
$where: function () {
for (var index in this.Roles)
if (this.Roles[index].Rolename == "THISROLENAME")
return this;
}
});
Note: I'm not sure why they designed regular MongoDB queries to not work if each of your embedded documents in the array has its own key, but hopefully in the future they'll fix that issue.
In the meantime this solution works great. I've tested it and it seems pretty fast.