Find the date difference in ElasticSearch - search

Let's say I have documents with the following fields:
{field1, field2, startdate, enddate}
I need to run some queries where some of the conditions will require the difference between the startdate and the enddate
In standard SQL, an example could be:
SELECT *,(2010-01-01-startdate) as diffstartdate, (2010-01-01-enddate) as diffenddate FROM Table1
How can I achieve this in elasticsearch?

Script Fields is what you need.
{
"query" : {
"match_all": {}
},
"script_fields" : {
"difference_between_two_dates" : {
"script" : "groovy.time.TimeCategory.minus(new java.util.Date(2010-01-01),new java.util.Date(doc['dateCreated'].value))"
}
}
}
Make sure that dynamic script is enabled in elasticsearch.yml.
script.disable_dynamic: false
You can refer to https://www.elastic.co/guide/en/elasticsearch/reference/1.4/search-request-script-fields.html for more information.
Hope it helps.

Related

CouchDB Search of Multiple Fields

I am trying to use CouchDB 3.1 for the first time. I'm trying to do a dynamic query where multiple fields can be searched and is totally optional. Example of my data:
{
"_id": "464e9db4d9216e1621b354794a0181d4",
"_rev": "1-fade491c3e255bbbfa60f1d7462fa9a2",
"app_id": "0000001",
"username": "john#gmail.com",
"transaction": "registration",
"customer_name": "John Doe",
"status": "complete",
"request_datetime": "2020-01-31 12:05:00"
}
So what I'm trying to do is, the documents can be searched by "transaction", "transaction" and "app_id", or combination of the fields "app_id" / "username" / "transaction" / "username" / "status" / "request_datetime" based on the search input from the user. (Some of the field such as "app_id" might be null based on the "transaction")
I have tried to make View to search by "app_id" and "transaction" :
function (doc) {
if(doc.transaction && doc.app_id) {
emit([doc.transaction, doc.app_id], doc);
}
}
But this is not gonna work when the app_id itself is null due to key in CouchDB is the index.
So my question is whether this can be achieved using vanilla CouchDB without using GeoCouch or Lucene? Do I need to make different views based on different combination of search fields?
Any help is greatly appreciated. Thank you very much.
With /db/_find, you can define a selector that accepts combination operators and condition operators. This lets you create simple and really complex queries. Given your document structure, such a selector could look as follows.
"selector":{
"$and":[
{
"app_id":{
"$eq":"0000001"
}
},
{
"username":{
"$eq":"john#gmail.com"
}
},
{
"request_datetime": {
"$gte": "2020-01-31 12:00:00",
"$lt": "2020-01-31 13:00:00"
}
}
]
}
The $or operator, combined with $eq and $exists may be used for checking fields that can be null. The $regex operator offers you even much more power.
Here's a simple example using CURL (replace with the name of your database).
curl -H 'Content-Type: application/json' -X POST http://localhost:5984/<db>/_find -d '{"selector":{"username":{"$eq": "john#gmail.com"}}}'

ElasticSearch search with querystring and verify another field

I need to translate the following SQL query to ES query:
SELECT *
FROM SKILL
WHERE SKILL.name LIKE 'text' and SKILL.type = 'hard'
I have tried the following using "elasticsearch" library for python3:
query = self.__es.search(index="skills",
body={"from" : skip, "size" : limit,
"query":
{"query_string":
{"query": 'text'}
})
and this worked well. But now, I don't know how to check that the field 'type' is equal to 'hard'.
How can I do that?
Thank you.
You have to use a bool query and in the "must" part put two queries, the full text one and a term one:
{
"query": {
"bool": [{
"match": {
"name": "this is a test"
}
}, {
"term": {
"type": "hard"
}
}]
}
}
Before this you have to store the type property as a keyword field.

Cloudant: How to create an index for "Sort" function?

The problem I am facing is on creating the correct index to query through my Cloudant database. The JSON data structure I am using looks similar to below.
{
"customer" : "123",
"time" : "2014-11-20"
}
I want to sort the documents based on the time. The index query that I used is:
curl -X POST 'https://<user>:<pass>#<user>.cloudant.com/<DB-name>/_index' -d '
{
"index": {
"fields": [
"customer",
"time"
]
}
}'
And the Query that I am using is:
curl -X POST 'https://<user>:<pass>#<user>.cloudant.com/<DB-name>/_find' -d '
{
"selector": {
"customer" : "123"
},
"sort": [
"time"
]
}'
The error code I am getting is "no_usable_index". Can anyone provide some insight into this problem?
Also, what would be different if the time were in the format:
"2014-11-20 11:50:00"? Essentially, I am trying to sort based on date and time. Is this possible?
The error message is telling you that there is no index to perform the sorting, or at least it can't find one. To help it find one, sort on customer and then on time, like so:
curl -X POST 'https://<user>:<pass>#<user>.cloudant.com/<DB-name>/_find' -d '
{
"selector": {
"customer" : "123"
},
"sort": [
"customer",
"time"
]
}'
This query is functionally identical, but now Cloudant Query will find the index.
Regarding your question about the other time format, the time field would still be treated as a string field for the purposes of sorting. In your case, that means you'll get the expected result.

Query the number of elements matching a filter using elastic.js?

I'm building a leaderboard with elasticsearch. I'd like to query all documents who have points greater than a given amount using the following query:
{
"constant_score" : {
"filter" : {
"range" : {
"totalPoints" : {
"gt": 242
}
}
}
}
This works perfectly -- elasticsearch appropriately returns all documents with points greater than 242. However, all I really need is the count of elements matching this query. Since I'm sending the result over the network, it would be helpful if the query simply returned the count, as opposed to all of the documents matching the filter.
How do I get elasticsearch to only report the count of documents matching the filter?
EDIT: I've learned that what I'm looking for is setting search_type to count. However, I'm not sure how to do this with elastic.js. Any noders willing to pitch in their advice?
You can use the query type count for exactly that purpose:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-search-type.html#count
This is an example that should help you:
GET /mymusic/itunes/_search?search_type=count
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"range": {
"year": {
"gt": 2000
}
}
}
}
}
}

Elasticsearch: how to get matching types list?

My elasticsearch index has 10 types in it. When searching for the term "test" I want to get all the documents that matched that query and a list of all the types that has a least one match for that query.
I know I can get this list by going over all results but I guess there's a better way..
Thanks!
Since facets have been deprecated (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-facets.html) and replaced with aggregations, here is the solution for aggregations:
{
"query": {
...
},
"aggs": {
"your_aggregation_name": {
"terms": {
"field": "_type"
}
}
}
}
Link to documentation: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html
Just managed to do that with elasticsearch facets like described here:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets.html#_facet_filter
In short you add this to your query:
"facets" : { "facet_name" : { "terms" : {"field" : "_type"} } }
Hope this help someone.

Resources