query multiple terms in multiple fields using elasticsearch - linux

I want to search for multiple terms in 2 different fields (title, and description), the operator should be OR. Meaning that if any records contains any of these terms (heart, cancer) then that record should be returned.
Here is my code:
curl -XGET 'localhost:9200/INDEXED REPOSITORY/_search?pretty' -H 'Content-
Type: application/json' -d'{"query" : {"constant_score" : {"filter" : {"terms"
: {"description","title" : ["heart","cancer"]}}}}}'
But, I get this error:
"error" : "SearchPhaseExecutionException[Failed to execute phase [query],
all shards failed; shardFailures {[6hWIW7xlSbSqKi4dNg_1bg][geo_021017cde]
[0]: SearchParseException[[geo_021017cde][0]: from[-1],size[-1]: Parse
Failure [Failed to parse source [{\"query\" : {\"constant_score\" :
{\"filter\" : {\"terms\" : {\"description\",\"title\" :
[\"heart\",\"cancer\"]}}}}
Am I missing anything?

I figured out how to resolve it:
{
"query": {
"constant_score": {
"filter": {
"bool": {
"should": [
{
"terms": {
"description": [
"heart",
"cancer"
]
}
},
{
"terms": {
"title": [
"heart",
"cancer"
]
}
}
]
}
}
}
}
}

Related

How could I push new element into sub document Post > Comments > Replies > likes as an array

I have a sample Post collection
[{
"_id" : ObjectId("5da832caeb173112348e509b"),
"body" : "Lorem Ipsu.",
"comments" : [
{
"comment" : "my sample comment",
"_id" : ObjectId("5db06e11d0987d0aa2cd5593"),
"replies" : [
{
"likes" : [
"5d999578aeb073247de4bd6e",
"5da85558886aee13e4e7f044"
],
"_id" : ObjectId("5db6a88f7c6cfb0d0c2b689b"),
"reply" : "my reply to this comment",
"user" : "5da85558886aee13e4e7f044"
}
],
"likes" : [
"5da85558886aee13e4e7f044",
]
},
],
}]
To add or remove element into comments.likes I can do like this,$push or $pull, it works with this below operation.
Post.updateOne(
{_id: req.body.id_post, "comments._id": req.body.id_comment},
{ $push: {"comments.$.likes": req.user._id}});
But if I want to push into replies.likes, could anyone please help to guide me?
I have tried something like this, but replies.likes is not updated.
db.posts.updateOne(
{ "comments.replies._id": Object("5db6a88f7c6cfb0d0c2b689b") },
{ "$push": { "comments.0.replies.$.likes": Object("5db6a88f7c6cfb0d0c2b689a") } },
function(err,numAffected) {
// something with the result in here
}
);
you can use array filter :
db.getCollection("test").updateOne(
{
"comments.replies": {
"$elemMatch": {
"_id": Object("5db6a88f7c6cfb0d0c2b689b")
}
}
},
{ "$set": { "comments.$[outer].reply.$[inner].likes": Object("5db6a88f7c6cfb0d0c2b689a") } },
{
"arrayFilters": [
{ "outer._id": ObjectId("5cd26a886458720f7a66a413") },
{ "inner._id": ObjectId("5cd26a886458720f7a66a415") }
]
}
)
don't mind ids

Bool and query on Elasticsearch 6.5.3

I'm working on ElasticSearch 6.5.3 and . Please find below my code:
from elasticsearch import Elasticsearch, helpers
def search(es_object, index_name, request):
toto = es_object.search(index=index_name, body=request)
return toto
fuzziness = 1
request1 = {
"query": {
"match" : {
"Family_name" : {
"query" : family_names,
"fuzziness": fuzziness,
}
}
},
"size" : size
}
request2 = {
"query": {
"match" : {
"First_name" : {
"query" : first_names,
"fuzziness": fuzziness,
}
}
},
"size" : size
}
result1 = search(es,ELASTICSEARCH_INDEX_NAME,request1)
result2 = search(es,ELASTICSEARCH_INDEX_NAME,request2)
I'd like to make a bool fuzzy query on firstname and family name. How can I do it please ?
I tried the following :
request = {
"bool": {
"must": [
{
"query": {
"match" : {
"First_name" : {
"query" : family_name,
"fuzziness": fuzziness,
}
}
},
"query": {
"match" : {
"Prénom" : {
"query" : firstname,
"fuzziness": fuzziness,
}
}
}
}
]
}
}
result = search(es,ELASTICSEARCH_INDEX_NAME,request)
I got the following error meaning that there is some problem in my query. It seems that I cannot combine two match queries having fuzziness simultaneously
RequestError: RequestError(400, 'parsing_exception', 'Unknown key
for a START_OBJECT in [bool].')
Your query is a bit wrong, you need to fix it like this:
{
"query": {
"bool": {
"must": [
{
"match": {
"First_name": {
"query": "family_name",
"fuzziness": fuzziness
}
}
},
{
"match": {
"Prénom": {
"query": "firstname",
"fuzziness": fuzziness
}
}
}
]
}
}
}
The reason is, that boolean query array already understand that it will be an object of query, so you don't need to specify it again

Elasticsearch: constructing bool query with filters

I have following document structure:
Movie:
{
id: int,
title: string,
language: string,
genre: string,
description: string,
cast: array[string],
directors: array[string],
(...)
}
Now, in the web interface, the user can choose (checkbox) the language, genre, directors etc and type some query to the search box.
Let's say I want to search within all thrillers (genre), that are in French or English (language), directed by James Cameron or George Lucas (directors) and I'm typing to the search box "abc" that I would like to find within title or description.
What I want as a result:
- only movies only in French or English
- only movies directed by James Cameron or George Lucas
- only thrillers
- movies that corresponds to "abc"
I'm not sure how to do the OR in the filters, but I have started from something like:
curl -X -XGET 'localhost:9200/movies/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query" : {
"constant_score" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"language" : "french"}},
{ "term" : {"language" : "english"}},
{ "term" : {"directors" : "James Cameron"}},
{ "term" : {"directors" : "George Lucas"}}
],
"filter" : [
{ "term" : {"genre" : "thriller"}}
]
}
}
}
}
}
'
Could you please give me some hints?
As I understand, you need a query like this: (language is A or B) and (directors is C or D) and (genre is E) and (title or description is F). In this case you need the following query:
{
"query": {
"bool": {
"filter": [
{
"terms": {
"language": [
"french",
"english"
]
}
},
{
"bool": {
"should": [
{
"match": {
"directors": "James Cameron"
}
},
{
"match": {
"directors": "George Lucas"
}
}
]
}
},
{
"term": {
"genre": "thriller"
}
},
{
"multi_match": {
"query": "abc",
"fields": [
"title",
"description"
]
}
}
]
}
}
}
filter query will work as AND condition but will get you the same score for all matched documents. If you need to vary score depending on subqueries match, you'd better to use must instead of filter. terms query will match if specified field contains at least one term. multi_match query will match if at least one field contains specified query

Mongo query using filter not fetching exact result?

My mongo table contains contains collection 'Shops' and data like the below:
{
"ShopId" : 9999,
"products" : [
{
"productId" : "1234",
"productName" : "abcd",
},
{
"productId" : "5678",
"productName" : "abc",
},
{
"productId" : "2345",
"productName" : "def",
}
],
}
There will be several shops in the table having a list of products.
Requirement:
I want to fetch the records having shopId=9999 and products matches the string abc
My query
model.Shops.aggregate([{$match:{"ShopId":9999}},{$project:{products:{$filter:{input:'$products',cond: {'productName':/abc/ }}}}}])
Problem:
It is fetching the productname:defwith the other data that matches productname:abc.
You can't use regex search with the $filter operator. The only way to achieve this is to unwind products, filter document and then re-group them in an array
model.Shops.aggregate([
{
$match:{
"ShopId":9999
}
},
{
$unwind:"$products"
},
{
$match:{
"products.productName":/abc/
}
},
{
$group:{
_id:null,
products:{
$push:{
"productName":"$products.productName",
"productId":"$products.productId"
}
}
}
}
])
output:
{
"_id":null,
"products":[
{
"productName":"abcd",
"productId":"1234"
},
{
"productName":"abc",
"productId":"5678"
}
]
}
to use it with a variable, declare your regex like this:
var regex: /abc/;
and then use it directly in the query
$match:{
"products.productName": regex
}
Below code worked on mongoshell for me, and your code was giving error to me, that Missing 'as' parameter to $filter.
db.Shops.aggregate([
{$match:{"ShopId":9999}},
{$project:{
products:{$filter:{input:'$products',as:"product",cond: { $eq: [ "$$product.productName", "abc" ] }}}
}}
])

bool query does not support filter

This is the query that throws the exception using ES 2.0:
bool query does not support filter
How to use Exists and Missing query?
Query:
{
"bool":{
"must":[
{
"bool":{
"should":[
{
"bool":{
"must":[
{
"range":{
"startDate":{
"lte":"2016-10-27T11:24:49.6616538+05:30"
}
}
}
],
"filter":[
{
"bool":{
"must_not":[
{
"exists":{
"field":"endDate"
}
}
]
}
}
]
}
}
]
}
}
]
}
}
Well first off, that error is generally from use on a 1.x version of Elasticsearch. (in that case you need a FilteredQuery)
Next it appears you have many levels of unnecessary nesting. Not sure if maybe you stripped other things out to make a simpler example. I have rewritten your query like this (and added the outer braces):
{
"query" : {
"bool" : {
"must" : [{
"range" : {
"startDate" : { "lte" : "2016-10-27T11:24:49.6616538+05:30" }
}
}
],
"filter" : [{
"bool" : {
"must_not" : [{
"exists" : { "field" : "endDate" }
}
]
}
}
]} }
}
Both your original query and my rewritten one work fine on my server (v2.3.1) so I'm guessing really you have ES 1.x ?
Also, if you are not leveraging the lucene scoring, and just want to return the documents (or apply your own sort) then you can drop the filter altogether and simplify it further:
{
"query" : {
"bool" : {
"must" : [{
"range" : {
"startDate" : { "lte" : "2016-10-27T11:24:49.6616538+05:30"}
}
}
],
"must_not" : [{
"exists" : { "field" : "endDate" }
}
]} }
}

Resources