search query in elasticsearch - node.js

I have documents like the below in my elasticsearch
{"method":"POST","url":"/saas/services/1.0/account/*/purchase/*/subscription/cancel"}
{"method":"POST","url":"/saas/services/1.0/account/*/purchase/*/cancel"}
I am searching these documents using node.js client. Below is the query I am sending.
Example 1 type : DSL
client.search({
index: 'my_node',
body: {
query: {
bool: {
must: {
match: { method: 'POST' },
match: { url: '/saas/services/1.0/account/*/purchase/*/cancel' }
}
}
}
}
}
Output
I am getting the other record with subscription cancel. The query is not matching the exact document. I tried the below query , it worked for this case but not working for few other test cases.
document
{"method":"POST","url":"/paas/service/1.0/act/*/purchase"}}
{"method":"GET","url":"/paas/service/1.0/act/*/purchase"}}
{"method":"PUT","url":"/paas/service/1.0/act/*/purchase"}}
Example 2 type : query string
client.search({
index: 'my_node',
q: 'method: POST AND url: /saas/services/1.0/account/*/purchase'
}
Output
I get the GET purchase document regardless of other two. Tried for few other documents, the method argument is not getting recognized.
How do I write elasticsearch query to search through the documents to match both the properties of method and url. i had tried query time boosting for the url but doesn't seem to work.
Edit - Mapping information
{
"nodeclient": {
"mappings": {
"logs": {
"properties": {
"method": {
"type": "string" },
"url": {
"type": "string" }
} } }
}
}

Try add quotation marks
client.search({ index: 'my_node', body: { "query": { "bool": { "must": {
"match": { "method": 'POST' }, "match": { "url":
'/saas/services/1.0/account//purchase//cancel' } } } } } }

I tried optimizing the query with Mirage plugin for elasticsearch queries. I was trying with different examples and saw the responses. Below is my final query that works for my scenario
{
"query": {
"bool": {
"must": [
{ "match_phrase": { "url": uri }},
{ "match": { "method": http } }
]}
}
match_phrase suited better for the url parameter. Also I missed the array part inside the must clause.

Related

search multiple field as regexp query in elasticsearch

I am trying to search by different fields such as title and description. When i type keywords, elasticseach must found something if description or title includes that i typed keywords. This is my goal. How can i reach my goal?
You can see the sample code that i used for one field.
query: {
regexp: {
title: `.*${q}.*`,
},
},
I also tried below one but it gave syntax error.
query: {
regexp: {
title: `.*${q}.*`,
},
regexp: {
description: `.*${q}.*`,
},
},
To do so, you need to use a bool query.
GET /<you index>/_search
{
"query": {
"bool": {
"should": [
{
"regexp": {
"title": ".*${q}.*"
}
},
{
"regexp": {
"description": ".*${q}.*"
}
}
]
}
}
}
You can find the documentation => [doc]

Conditionally adding term and multi_match filters to elasticsearch with nodejs client

I am using ElasticSearch 7.9 with a nodejs client. I have the following query :
{
"query": {
"bool": {
"must":[
{ "terms" : { "id" : ["5f0d06fb5112231eb89eb819", "5f0d06fb5112231eb89eb817"] } },
{"query_string": {
"query": "(News) OR (Entertainent)",
"fields": [ "topics", "subTopics", "categories"]
}
},
{
"multi_match": {
"query": "publisher",
"fields": ["text", "name", "title", "subtitle", "description"]
}
}
]
}
}
}
I want to be able to conditionally add the terms filter for id if list of ids coming in to the nodejs/js function is not empty. Similarly for the multi_match query text as well. Add the multi_filter only if the incoming text is not empty
Should all queries be pre-constructed or is it possible to have conditional blocks and add only if the empty text or array of Ids are not empty.
My current method expects both ids and text input to the method to have valid values but these could be empty. Do I separate methods to handle the empty conditions
export const searchResults = async (text, ids) => {
const response = await client.search({
index: "new_index", //customer.id
type: "_doc",
body: {
query: {
bool: {
must: [
{terms: {"id": ids}},
{query_string: {
query: "(News) OR (Entertainent)",
fields: [ "topics", "subTopics", "categories"]
}
},
{
multi_match: {
query: text,
fields: ["text", "name", "title", "subtitle", "description"],
}
}
],
}
}
},
});
return response?.hits?.hits.map(({_source}) => _source) || [];
};
any help is really appreciated.
In a production environment and managing client based applications you should use search-templates, where you can use conditional blocks of queries. Besides, if you would want to change your query you would not neet to redeploy your app, just change it on ES.

mongoosastic search with two fields with and condition

I have a chatting applications developed in Angular js, Node.js, MongoDB with elastic search integration. I had provided search functionality for chats, which user can enter any combination. Options are chat message, user and date.
So i want to search in elastic search db with help of nodejs, with mutiple field combination. For example, 1) search with username='mohan' and the date='anydate', 2) username='mohan' and chatmessage='Hi there'.
So the result should come which satisfy both conditions.
How can we achieve this using mongoosastic? I tried with below query. But it is giving result with OR condition, I want with AND condition.
{
"query": {
"bool": {
"should": [{
"match": {
"feedMsg": "Hi there"
}
}, {
"match": {
"userId": 'mohan'
}
}, {
"range": {
"feedTime": {
"from": '27/10/2016',
"to": '27/10/2016'
}
}
}]
}
}
}
I found the solutions. Bool Query with must is working for me.
{
"bool" : {
"must" : [],
"should" : [],
"must_not" : [],
"filter": []
}
}
must- All of these clauses must match. The equivalent of AND.
must_not - All of these clauses must not match. The equivalent of
NOT.
should - At least one of these clauses must match. The equivalent of OR.
filter - Clauses that must match, but are run in non-scoring,
filtering mode.
You should use this format, it really works...
var query = {
query_string: {
filtered: {
query: {
multi_match: {
query: req.query.q, // or anything you will put here
}
},
filter: {
term: {
'field': value
}
}
}
}
}

Elasticsearch - Unique counts of a field, filter by the number of documents that contain a specific value in an other field

I'm new to Elasticsearch and I'm trying to do kind of a complex search but I can't found how to do it, or even if it's possible.
I use Elasticsearch to store document.
All of this document have a userId field which is potentially the same in multiple documents.
They also have a documentType field which contains a string.
I want to have a unique count of userId that have at least n number of a DocumentType.
Currently if n = 1 I'm able to retrieve the unique count with this request:
{
"aggs": {
"docType_file": {
"filters": {
"filters": {
"documentType:\"file\"": {
"query": {
"query_string": {
"query": "documentType:\"file\"",
}
}
}
}
},
"aggs": {
"unique_user": {
"cardinality": {
"field": "userId"
}
}
}
}
}
}
But if I want n to be superior to 1 (or if I want to do an other operation, less, equal or range) I don't find a way to do it. I have look in the different aggregations but I don't find how to combine them to retrieve this.
Is it possible to do that in Elasticsearch?
UPDATE:
I found an other way to do the query which may be more interesting to do an other aggregations afterward.
{
"query": {
"filtered": {
"query": {
"query_string": {
"query": "documentType:\"file\""
}
}
}
},
"aggs": {
"unique_user": {
"cardinality": {
"field": "userId",
"precision_threshold": 40000
}
}
}
}
But I still don't know how to filter after that and I kind of think that I'm taking the problem the wrong way but I don't see any other solution.

ElasticSearch MultiField Search Query

I have an endpoint that I am proxying into ElasticSearch API for a simple user search I am conducting.
/users?nickname=myUsername&email=myemail#gmail.com&name=John+Smith
Somet details about these parameters are the following
All parameters are optional
nickname can be searched as a full text search (i.e. 'myUser' would return 'myUsername')
email must be an exact match
name can be searched as full text search for each token (i.e. 'john' would return 'John Smith')
The ElasticSearch search call should treat the parameters collectively as AND'd.
Right now, I am not truly sure where to start as I am able to execute the query on each of the parameters alone, but not all together.
client.search({
index: 'users',
type: 'user',
body: {
"query": {
//NEED TO FILL THIS IN
}
}
}).then(function(resp){
//Do something with search results
});
First you need to create the mapping for this particular use case.
curl -X PUT "http://$hostname:9200/myindex/mytype/_mapping" -d '{
"mytype": {
"properties": {
"email": {
"type": "string",
"index": "not_analyzed"
},
"nickname": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}'
Here by making email as not_analyzed , you are making sure only the exact match works.
Once that is done , you need to make the query.
As we have multiple conditions , it would be a good idea to use bool query.
You can combine multiple queries and how to handle them using bool query
Query -
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "qbox"
}
},
{
"prefix": {
"nickname": "qbo"
}
},
{
"match": {
"email": "me#qbox.io"
}
}
]
}
}
}
Using the prefix query , you are telling Elasticsearch that even if the token starts with qbo , qualify it as a match.
Also prefix query might not be very fast , in that case you can go for ngram analyzer - http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/analysis-ngram-tokenizer.html

Resources