I'm using the elasticsearch client for doing some search query using constant_score and aggregations but it's throwing the exception:
[parsing_exception] [constant_score] malformed query, expected [END_OBJECT] but found [FIELD_NAME]
This is where I'm creating the query and calling the search function:
fetchData: function fetchFn(req, res, next) {
var model = new urlModel();
util.log('Fetching data from ES::');
var query = buildAggregateUrl(req.reqData);
// if (req.reqData['domain']) {
// var termFilter = { "term": { "domain": req.reqData.domain } };
// query.constant_score.filter.bool.must.push(termFilter);
// }
model.search({ query }, function (er, re) {
if (re) {
req.sendResult = re;
}
next(er);
});
function buildAggregateUrl(opts) {
var query = {
constant_score: {
filter: {
bool: {
must: [{
"range": {
"timestamp": {
"gte": opts.startTime,
"lte": opts.endTime
}
}
}]
}
}
},
aggs: {
success: {
scripted_metric: {
init_script: "params._agg.succ=0;",
map_script: "if(doc.status.value=='success'){params._agg.succ+=1}",
combine_script: "return params._agg.succ",
reduce_script: "int sum=0;for (a in params._aggs){sum+=a}return sum"
}
},
failure: {
scripted_metric: {
init_script: "params._agg.fail=0;",
map_script: "if(doc.status.value=='failure'){params._agg.fail+=1}",
combine_script: "return params._agg.fail",
reduce_script: "int sum=0;for (a in params._aggs){sum+=a}return sum"
}
}
}
};
return query;
}
}
And this is what the search function looks like:
es_model.prototype.search = function (opts, cb) {
var query = {
index: this.esConfig.index,
type: this.esConfig.type,
body: {query:opts.query}
};
console.log('Query ===> ',query);
this.client.search(query, cb);
}
I can't figure out where the problem is with the syntax.I tried wrapping the constant_score key withtin query as well but it doesn't seem to work.
You're simply missing a query element at the top level:
{
query: {
constant_score: {
filter: {
bool: {
must: [{
"range": {
"timestamp": {
"gte": opts.startTime,
"lte": opts.endTime
}
}
}]
}
}
}
},
aggs: {
success: {
scripted_metric: {
init_script: "params._agg.succ=0;",
map_script: "if(doc.status.value=='success'){params._agg.succ+=1}",
combine_script: "return params._agg.succ",
reduce_script: "int sum=0;for (a in params._aggs){sum+=a}return sum"
}
},
failure: {
scripted_metric: {
init_script: "params._agg.fail=0;",
map_script: "if(doc.status.value=='failure'){params._agg.fail+=1}",
combine_script: "return params._agg.fail",
reduce_script: "int sum=0;for (a in params._aggs){sum+=a}return sum"
}
}
}
}
Also note that your client code should look like this:
es_model.prototype.search = function (opts, cb) {
var query = {
index: this.esConfig.index,
type: this.esConfig.type,
body: opts.query
};
this.client.search(query, cb);
}
Related
Let's say I have the following schema:
query Publications($id: ProfileId!) {
publications(
request: { profileId: $id }
) {
items {
typename
}
}
}
And I get a result like so:
{
"data": {
"publications": {
"items": [
{
"typename": "Article"
},
{
"typename": "Post"
},
{
"typename": "Post"
},
]
}
}
}
How do I filter my results so I only get the "typename": "Article"?
One way is to add a second optional parameter to your query:
query Publications($id: ProfileId!, $typename: String) {
publications(
request: { profileId: $id , typename: $typename}
) {
items {
typename
}
}
}
Then in your resolver, if you see that typename has a value, filter your results to match.
I want to combine the result of a function_score with other clauses inside a bool query.
{
'bool': {
'must': [
{
'function_score': {
'query': {
'exists': {
'field': 'field_A',
}
},
'script_score': {
'script': {
'source': "doc['field_A'].value / (doc['field_A'].value + params.pivot)",
'params': {
'pivot': 1000,
}
}
},
},
},
{
'rank_feature': {
'field': 'field_B',
}
}
]
}
}
The score stays the same, whether I include the function_score clause or not.
If I replace script_score with a field_value_factor, it does get reflected in the final score.
I'm trying to delete all documents where a certain property has a certain value. The code below is my best attempt, but the ES API returns a parse error:
const userProperty = "couchDbOrigin";
client.deleteByQuery({
index: "_all",
body: { query: { bool: { must: [{ terms: { [userProperty]: user } }] } } }
});
What is wrong with this code?
terms query expect criteria as an array :
so you should use :
client.deleteByQuery({
index: "_all",
body: { query: { bool: { must: [{ terms: { [userProperty]: [user] } }] } } }
});
But if you delete document for one user at a time, you should use a term query that expects a single value and can perform better
client.deleteByQuery({
index: "_all",
body: { query: { bool: { must: [{ term: { [userProperty]: user } }] } } }
});
I am populating a table using graph QL query :
The graphql query looks like :
const DESSERT_QUERY = gql`
query DESSERT_QUERY($where: dessert_bool_exp) {
dessert(where: $where) {
name
calories
fat
carbs
}
}
`;
Query Variables :
{"where":
{
"name": {
"_in": ["xyz"]
},
"calories": {
"_eq": 1
},
"fat": {
"_eq": 606
},
"carbs": {
"_eq": 1
},
}
}
How to implement an OR query.
Any guidance is appreciated. Thanks
The correct GraphQL Query Variables is :
{"where":
{
"name": {
"_in": ["xyz"]
},
"calories": {
"_eq": 1
},
"_or": [{"fat": {
"_eq": 606
}},
{"carbs": {
"_eq": 1
}}]
}
}
Ive setted up elasticsearch with a NodeJS Server and need a working boolean query that checks different conditions in the search. How to do that?
I am using mongoosastic(query DSL) with NodeJS and the following query to get the results
mapping Function
async function mapMongoToElastic() {
return new Promise((resolve, reject) => {
console.log("---------Mapping gets created---------");
Product.createMapping(
{
mappings: {
product: {
properties: {
ArtNumber: { type: "text" },
Title: {
type: "text",
fields: {
keyword: {
type: "keyword"
}
}
},
DisplayPrice: { type: "double" },
CF_Deliverytime: { type: "text" },
Description_Short: { type: "text" },
MainCat: {
type: "text",
fields: {
keyword: {
type: "keyword"
}
}
},
ItemCat: {
type: "text",
fields: {
keyword: {
type: "keyword"
}
}
},
Deeplink1: { type: "text" },
Img_url: { type: "text" },
CF_img_url2: { type: "text" },
CF_img_url3: { type: "text" },
CF_Availability: { type: "text" },
CF_Productrating: {
type: "text",
fields: {
keyword: {
type: "keyword"
}
}
},
CF_Discount: {
type: "text",
fields: {
keyword: {
type: "keyword"
}
}
},
Shop: {
type: "text",
fields: {
keyword: {
type: "keyword"
}
}
}
}
}
}
},
function(err, mapping) {
if (err) {
console.log("error creating mapping (you can safely ignore this)");
console.log(err);
resolve(err);
} else {
console.log("X - ElasticSearch Mapping Created");
resolve(mapping);
}
}
);
});
}
Query function
async function asyncSearchWithOutFilter(query, from, to) {
return new Promise((resolve, reject) => {
Product.esSearch(
{
from: from,
size: to,
query: {
multi_match: {
query: query.suche,
fields: [ "Title^10", "ItemCat^5" ]
}
},
aggs: {
mainCats: {
terms: { field: "MainCat.keyword" }
},
itemCats: {
terms: { field: "ItemCat.keyword" }
},
itemShops: {
terms: {
field: "Shop.keyword"
}
}
}
},
{},
async (err, results) => {
if (err) throw err;
let res = await results;
/* console.log("-------------Total Hits---------------");
console.log(res.hits.total);
console.log("-----------------------------------------");
console.log("-------------Shops---------------");
console.log(res.aggregations.itemShops.buckets);
console.log("-----------------------------------------");
console.log("-------------Item-Categories---------------");
console.log(res.aggregations.itemCats.buckets);
console.log("-----------------------------------------"); */
resolve(res);
}
);
});
}
Expected results:
- Query for "TV"
Results:
Products with Title "TV" in
- if Category has "TV" also, rank it up higher.
Problem:
Smart-TV-Controller is also listed if searched for "TV", but not expected if someone is searching for a "TV"
help appreciated.
Seems like you are trying to get exact match. You already have keyword type sub-field for both the fields Title and ItemCat. So instead use keyword field in match query.
query: {
multi_match: {
query: query.suche,
fields: [ "Title.keyword^10", "ItemCat.keyword^5" ]
}
}
If you are not looking for exact match in Title then another way can be to set fields as below:
fields: [ "Title^10", "ItemCat.keyword^5" ]