ElasticSearch API for user entered boolean/advanced search queries - api

In Kibana I'm able to enter queries with AND / OR / NOT / "..." etc, but all examples I can find for the API (Python or NodeJS or .NET) use the Elasticsearch JSON query format to build queries in code. I would like users to be able to enter 'hot AND soup' or '"hot soup" AND cabbage"' etc which are possible in Lucene and Kibana but I cannot find how to use those via the API. I read all SO entries and Elasticsearch docs I could find about the subject but still missed it.
Is it at all possible and if it is, where can I find examples of that? As I cannot find it, it might not be possible at all; I just want to make sure.

Whatever the language you're programming in, you simply need to use the query_string query and pass the use input in there.
GET /_search
{
"query": {
"query_string": {
"query": "\"hot soup\" AND cabbage",
"default_field": "content"
}
}
}
Beware, though, that the query_string query is very sensitive to the syntax, so your users might not enter correct queries. To alleviate that, a more permissive query would be the simple_query_string query

Related

REST GET mehod: Can return a list of enriched resources?

I have a doubt when I'm designing a REST API.
Consider I have a Resource "Customer" with two elements in my server, like this:
[
{
name : "Mary",
description : "An imaginary woman very tall."
},
{
name : "John",
description : "Just a guy."
}
]
And I want to make an endpoint, that will accept a GET request with a query. The query will provide a parameter with a value that will make an algorithm count how many occurrences for this text are there in all of its parameters.
So if we throw this request:
GET {baseURL}/customers?letters=ry
I should get something like
[
{
name : "Mary",
description : "An imaginary woman very tall.",
count : 3
},
{
name : "John",
description : "Just a guy.",
count : 0
}
]
Count parameter can not be included in the resource scheme as will depend on the value provided in the query, so the response objects have to be enriched.
I'm not getting a list of my resource but a modified resource.
Although it keeps the idempotent condition for GET Method, I see it escapes from the REST architecture concept (even the REST beyond CRUD).
Is it still a valid endpoint in a RESTful API? or should I create something like a new resource called "ratedCustomer"?
REST GET mehod: Can return a list of enriched resources?
TL;DR: yes.
Longer answer...
A successful GET request returns a representation of a single resource, identified by the request-target.
The fact that the information used to create the representation of the resource comes from multiple entities in your domain model, or multiple rows in your database, or from reports produced by other services... these are all implementation details. The HTTP transfer of documents over a network application doesn't care.
That also means that we can have multiple resources that include the same information in their representations. Think "pages in wikipedia" that duplicate each others' information.
Resource identifiers on the web are semantically opaque. All three of these identifiers are understood to be different resources
/A
/A?enriched
/B
We human beings looking at these identifiers might expect /A?enriched to be semantically closer to /A than /B, but the machines don't make that assumption.
It's perfectly reasonable for /A?enriched to produce representations using a different schema, or even a different content-type (as far as the HTTP application is concerned, it's perfectly reasonable that /A be an HTML document and /A?enriched be an image).
Because the machines don't care, you've got additional degrees of freedom in how you design both you resources and your resource identifiers, which you can use to enjoy additional benefits, including designing a model that's easy to implement, or easy to document, or easy to interface with, or easy to monitor, or ....
Design is what we do to get more of what we want than we would get by just doing it.

How to limit Podio API output for complex item resources

Is it possible to limit API response from the POST /item/app/{app_id}/filter/ for a complex resources with a lot of fields set? I know there is fields param and it can be used with some predefined views, like items.view(micro), but this is not a solution for us. We need to explicitly define which fields should be returned, to have in the response only needed fields (optimize the output length as much as possible, but have all needed fields). Can we somehow achieve this by available for now API params or could Podio consider to introduce such functionality in the future API revisions?
You can specify the fields() decorator, to add desired fields to your view.
items.view(micro).fields(fields,created_on,last_edit_on)
Unfortunately I don't think it is possible to further filter the number of Podio Application's Fields returned under the REST response's fields field (ugh 😓).
I couldn't find a way to filter on the Fields defined by the user on the Application.
E.g.
[
{
"fields": [
{
"label": "My item field"
"field_id": 123456778,
"external_id": "my-item-field"
}
]
}
]
It's not possible to filter by my-item-field.
As I know, Rest Api doesn't allow you to limit (select) output fields. (As GraphQL can do)
So, while Podio is on Rest Api - you can't do that.

How can I get and use the properties I need from this GraphQL API using Dart?

Before you start reading: I have looked at the GraphQL documentation, but my usecase is so specific and I only need the data once, and therefore I allow myself to ask the community for help on this one to save some time and frustration (not planning to learn GraphQL in the future)
Intro
I am a CS student developing an app for Flutter on the side, where I need information about the name and location of every bus stop in a specific county in Norway. Luckily, there's an open GraphQL API for this (API URL: https://api.entur.io/stop-places/v1/graphql). The thing is, I don't know how to query a GraphQL API, and I do not want to spend time learning it as I am only going to fetch the data once and be done with it.
Here's the IDE for the API: https://api.entur.io/stop-places/v1/ide
And this is the exact query I want to perform as I want to fetch bus stops located in the county of Trondheim:
{
stopPlace(stopPlaceType: onstreetBus, countyReference: "Trondheim") {
name {
value
}
... on StopPlace {
quays {
geometry {
coordinates
}
}
}
}
}
The problem with this query though, is that I don't get any data when passing "Trondheim" to the countyReference (without countyReference I get the data, but not for Trondheim). I've tried using the official municipal number for the county as well without any luck, and the documentation of the API is rather poor... Maybe this is something I'll have to contact the people responsible for the API to figure out, which shouldn't be a problem.
But now back to the real problem - how can I make this query using the GraphQL package for Dart? Here's the package I'm planning to use: (https://pub.dev/packages/graphql)
I want to create a bus stop object for each bus stop, and I want to put them all in a list. Here is my bus stop model:
class BusStop with ChangeNotifier {
final String id;
final String name;
final LatLng location;
BusStop({
this.id,
this.name,
this.location
});
}
When it comes to authentication, here's what the documentation says:
This API is open under NLOD licence, however, it is required that all consumers identify themselves by using the header ET-Client-Name. Entur will deploy strict rate-limiting policies on API-consumers who do not identify with a header and reserves the right to block unidentified consumers. The structure of ET-Client-Name should be: "company - application"
Header examples: "brakar - journeyplanner" "fosen_utvikling - departureboard" "norway_bussekspress - nwy-app"
Link to API documentation: https://developer.entur.org/pages-nsr-nsr
Would be great to know how I should go about this as well! I'm grateful for every answers to this, I know I am being lazy here as of learning GraphQL, but for my usecase I thought it would take less time and frustration by asking here!
Getting the query right
First of all you seem to have GraphQL quite figured out. There isn't really much more to it than what you are doing. What queries an API supports depends on the API. The problem you seem to have is more related to the specific API that you are using. I might have figured the right query out for you and if not I will quickly explain what I did and maybe you can improve the query yourself:
{
stopPlace(stopPlaceType: onstreetBus, municipalityReference: "KVE:TopographicPlace:5001") {
name {
value
}
... on StopPlace {
quays {
geometry {
coordinates
}
}
}
}
}
So to get to this I started finding out more about "Trondheim" bei using the topographicPlace query.
{
topographicPlace(query: "Trondheim") {
id
name {
value
}
topographicPlaceType
parentTopographicPlace {
id
name {
value
}
}
}
}
If you do that you will see that "Trondheim" is not a county according to the API: "topographicPlaceType": "municipality". I have no idea what municipality is but the is a different filter for this type on the query that you provided. Then putting "Trondheim" there didn't yield any results so I tried the ID of Trondheim. This now gives me a bunch of results.
About the GraphQL client that you are using:
This seems to be an "Apollo Client" clone in Dart. Apollo Client is a heavy piece of software that comes with a lot of awesome features when used in a frontend application. You probably just want to make a single GraphQL request from a backend. I would recommend using a simple HTTP client to send a POST request to the GraphQL API and a JSON body (don't forget content type header) with the following properties: query containing the query string from above and variables a JSON object mapping variable names to values (only needed if you decide to add variables to your query.

How to filter fields in documents with security rules

I am experimenting with Cloud Firestore security rules. Is it possible to filter document fields?
For example if you have a document
{
name: "John Doe",
email: "doe#example.com"
}
then some users aren't allowed to get the document with the email address. Their application requests the document with
firebase.firestore.doc('users/doe-uid')
and gets this document
{
name: "John Doe",
}
If yes, how?
I think it should be possible because the Cloud Firestore Security Rules Reference says in the first sentence (emphasis is mine):
Cloud Firestore Security Rules are used to determine who has read and write access to collections and documents stored in Cloud Firestore, as well as how documents are structured and what fields and values they contain.
However I couldn't find anything in the reference telling me how to filter out fields.
Firestore rules are not filters, they're a server-side validation of document queries, meaning that you access (or not) the whole document, not particular fields.
The piece of documentation you mentionned means that you can do data validation on fields.
Here is a basic example of rules validating data on a write query (via request.resource.data) :
match /users/{userId} {
allow write: if request.resource.data.age is int;
}
Here is another basic example that uses an existing field to validate a read query (via resource.data) :
match /articles/{articleId} {
allow read: if resource.data.isPublished == true;
}
To filter out fields, you have do it client side, after the query.
Now If you want to secure access to certain fields, you have to create another collection (look into subcollections) with a different set of rules, and make another query that will match these rules.

How to query RavenDB using HTTP API for all documents of a type

I'm trying to query RavenDB using the HTTP client for all documents by type.
I would like a collection of the documents with a given type.
I understand that there might be limitations only the first 1024 documents will be returned.
I am well under that number and besides it's for a proof of concept.
I am able to obtain all the documents using the following syntax:
http://localhost:8080/databases/{database name}/docs/
I see that I could use the #metadata field to get the documents of the type I want but I don't know the syntax.
Since the HTTP api allows you to query indexes, I attempted to write a static index.
When I wrote the index from Raven Studio, the index was not returning the documents of the type I wanted. It was giving zero results.
from doc in docs.MyType
select new { doc};
I also tried this:
from doc in docs
let Tag = doc["#metadata"]["Raven-Entity-Name"]
where Tag == "MyType"
select new { doc};
You can do it using:
http://localhost:8080/databases/{database name}/indexes/dynamic/CollectionName