What is the correct query parameter for "match-all" in a REST filter when there is a default? - api

If a REST API endpoint gets all, then filters are easy. Lack of a filter means "get all results".
GET /persons - gets all persons
GET /persons?name=john - gets all persons with name of "john"
But if there is a default, then I need some way to explicitly not set the default filter. Continuing the above example, if each person has a state, "approved" or "pending", and if my system is set such that if I do not explicitly specify a state, it will return all "approved":
GET /persons - gets all approved persons, because defaults to state=approved
GET /persons?state=approved - same thing, gets all approved persons
GET /persons?state=pending - gets all pending persons
How do I get all persons? What if there are 10 possible states? Or 100?
I can think of a few ways:
GET /persons?state=any - but then I can never use the actual state any
GET /persons?state=* - would work, but feels strange? Or is it?
GET /persons?state= - some URL parsing libraries would complain about a blank query parameter, and does this not imply "state is empty" as opposed to "state is anything"?
How do I say in my GET, "override the default for the state to be anything"?

Maybe this could work for you:
GET /persons?state - gets all persons that have a state name, no matter which value
GET /persons?state= - gets all persons that have an empty value for the state name
You probably don’t need to differentiate between these two situations, so you could use either one for getting all persons with the state name (I just think that the variant without = is more beautiful).
FWIW, the application/x-www-form-urlencoded format (i.e., typically used in HTML forms) doesn’t differ between an empty and no value.
As far as the URI standard is concerned, this name-value pair syntax in the query component is only a convention anyway, so you can use whichever syntax/semantics you wish.

I don't think there is one answer to this question. As long as you document that the default state is approved well I don't think it matter to the clients if you pass any, * etc. All of your proposals are fine except the last one. I don't think that is a good one.
If I was designing the API I would use all and keep this as a standard. I would also recommend to use paging for all endpoints that returns list of elements. I use offset and limit as paging query parameters. In my API I return 20 elements as default if the client haven't specified another paging criteria.

Related

Confused with the "updates context keys with" feature..

do I need to define the key that gets updated with the new asnwer from the user, or do I set the condition that I need to be satisfied to proceed? The explainer on the right says both: Describe the context keys that will be updated by your action and if you need more than one condition to be met, you can use '&&' etc etc..
Can anyone explain this feature functionality better? thanks
I also had confusions in understanding the context part, but later figured it out.
Let me try to explain the way I understood.
In a story you want some actions to be executed and also you want your actions to return some result or rather I would say, you want some variables to be set with some value within your action that you will use in the next step of your conversation in wit.ai. Those variables can be defined in wit.ai as context keys.
Below is an example:
I have a credit card and I want to report lost card using bot. I say I lost my credit card and give the bot required information for it to fetch my card details, then it will call an action BlockCard. As a result of execution, I need the name, last 4 digits of the card and reference number for the raised complaint. These 3 variables need to be filled in while the action BlockCard runs. These are declared in wit.ai as context keys with '&&'. I would use these variables in the further conversation.
Note: You need to make sure that the name of context keys and name of the actions declared in wit.ai and the names used in your code are same.
Have a look at wit story:
https://wit.ai/Nayana-Manchi/CreditCardApp/stories/f7d77d9e-e993-428f-a75e-2e86f0e73cb3

API with an non define number of parameters

I am building an API where I allow the users to passes 2 different list of custom fields.
The API is basically this:
def action(type, name, date, name_custom_1, name_custom_2, name_custom_3, date_custom_1, date_custom_2, date_custom_3, date_custom_4)
So type, name date are parameter of this API and are mandatory.
name_custom_*, and date_custom_* are optionals, I could have 0, 1, 2, 3 ...
I am putting a limit to 3 for name_custom and 4 to date_cutom for technical reasons, but eventually this limit can get increased (but never extremely will never be completely remove)
Now my question is, what is the best way to make this API, from a user point of view:
def action(type, name, date, name_custom_1, name_custom_2, name_custom_3, date_custom_1, date_custom_2, date_custom_3, date_custom_4)
or
def action(type, name, date, names_custom, dates_custom):
Where names_custom and dates_custom are a list which can not be bigger than X.
I am struggling between both and find value and logic in both. Any suggestions?
The list parameters give a cleaner solution, because:
There are less arguments in the function signature, making the documentation easier to read for humans.
It is more resilient to change. Suppose you decide to change the maximum number of custom arguments from 4 to 5. In the list approach, the change is simpler.
Even having 5 arguments in a function call is more than usual, and often considered sloppy (see How many parameters are too many?). You may want to consider introducing a class, or a few classes in here. Depending on your application, maybe it makes sense to create class that encapsulates the name and the list of custom names, and a class that encapsulates the date and the list of custom dates? And perhaps the action itself is better off being a class with a number of setter methods?
In other words, if your functions become long, or argument lists become long, it is often a sign that there are classes waiting to be discovered underneath your design.

Cypher-Neo4j Node Single Property change to Array

Following is a Node we having in DB
P:Person { name:"xxx", skill:"Java" }
and after awhile, we would like to change the Skill to skill array, is it possible?
P:Person { name:"xxx", skill:["Java", "Javascript"] }
Which Cypher query should I use?
If you have a single skill value in skill, then just do
MATCH (p:Person)
WHERE HAS (p.skill)
SET p.skill=[p.skill]
If there are multiple values you need to convert to an array such as P:Person { name:"xxx", skill:"Java","JavaScript" } then this should work:
MATCH (p:P)
SET p.skill= split(p.skill,",")
In fact, I think your real problem here is not how to get an array property in a node, but how to store it. Your data model is wrong in my opinion, storign data as array in neo4j is not common, since you have relations to store multiple skills (in your example).
How to create your data model
With your question, I can already see that you have one User, and one User can have 1..n skills.
I guess that one day (maybe tomorrow) you will need to know which users are able to use Java, C++, PHP, and every othre skills.
So, Here you can already see that every skill should have its own node.
What is the correct model in this case?
I think that, still with only what you said in question, you should have something like this:
(:Person{name:"Foo"})-[:KNOWS]->(:Skill{name:"Bar"})
using such a data model, you can get every Skill known by a Person using this query:
MATCH (:Person{name:"Foo"})-[:KNOWS]->(skill:Skill)
RETURN skill //or skill.name if you just want the name
and you can also get every Person who knows a Skill using this:
MATCH (:Skill{name:"Bar"})<-[:KNOWS]-(person)
RETURN person //Or person.name if you just want the name
Keep in mind
Storing array values in properties should be the last option when you are using neo4j.
If a property can be found in multiple nodes, having the same value, you can create a node to store it, then you will be able to link it the other nodes using relations, and finding every node having the property X = Y will be easier.

How to identify Drive ID?

The new Google Drive Android API has 2 types of string IDs available, the 'resource' ID and the 'encoded' ID.
'encoded' id from DriveId.encodeToString()
"DriveId:CAESHDBCMW1RVVcyYUZKZmRhakIzMDBVbXMYjAUgssy8yYFRTTNKRU55"
'resource' id from DriveId.getResourceId()
"UW2aFJfdajB3M3JENy00Ums0B1mQ"
In the process I end-up with a string that can contain any one of them (result of some timing issues). My question is:
If I need to 'parse' the string in order to identify the type, is there a characteristic I can rely on? For instance:
'encoded' id will always start with 'DriveId:' substring
'resource' id will have some length limit
can I abuse error return from 'decodeFromString()'?
or should I form (pre-pend) the string container with my own tag? What could be the minimal 'safe' tag (i.e. what will never appear in the beginning of these ids) ?
Please point me in the right direction so I don't have to re-do it with the next release.
I have run into yet another issue that should be mentioned here so others don't waste time falling into the same pit. The 'resourceID' can be ported and will remain unique for the object it identifies, where 'encodedID' has only 'device' scope. Means that you CAN'T transfer 'encodedID' to another device (with the same account) and try to retrieve file/folder with it. So I assume it is unique to a Google Play Services instance.
Please do not rely on any formatting of either ID type. This are subject to change without notice.
If you need to use both, and track the differences between them you should have your own method of doing so within your app.
Really, you should probably always just store the encoded ID since this one is always guaranteed to present, and if it contains a resourceId, its easy to get back out.

Is a RESTful PUT with no data "kosher," or should a DELETE always be used?

I have a RESTful route that works on an array field of a resource, such:
PUT /:id/mylist
When I do a PUT, I throw an error if the input is empty. That is, if an empty array is passed. I require at least one element in the array. So if the resource has an array of nine elements, and the route is called to PUT three, those three replace the existing nine.
But you cannot pass in no elements, because that would erase the nine and leave nothing.
Having no element IS ALLOWED, however - it just seems to me that allowing the array to be "cleared" in a PUT is wrong, and that it should only be done thusly:
DELETE /:id/mylist
Am I wrong? Are both okay? Is one preferred over the other?
I would think that doing DELETE on a list resource would infer that the list is no longer there and future GET requests to the URL would return a 404.
However, doing a PUT with an empty list would cause future GET requests to return a 200 and an empty list (however that is represented).
I would say both are valid approaches, it just depends one what are the most natural semantics for the resource.