elasticsearch: cannot search for # symbol - elasticsearch

Our mapping looks like this:
mappings: {
entry: {
properties: {
id: { type: 'string' },
name: { type: 'string' },
creationTimestamp: { type: 'date', format: 'date_time' },
lastTimestamp: { type: 'date', format: 'date_time' }
}
}
}
There are docs that contain # symbols in the name, like for example "#TITLE#_30". However, I am not able to search for the # symbol. Searching for name:*title* or name:*_30* works fine, but when trying name:*#title* I get no results.
Which tokenizer do I have to use so that this is possible? What our end-users want to do is just case insensitive searches with wildcards.
EDIT
The query looks like this:
query: {
filtered: {
filter: {
bool: {
must: [{
range: {
creationTimestamp: {
gte: startdate.toISOString(),
lte: enddate.toISOString()
}
},
query: {
query_string: {
query: 'name:*title*' // e.g
}
}
}]
}
}
}
}
P.S. we use es v1.7
EDIT 2
Tried the 2 options from How to modify standard analyzer to include #? but they don't work for me.
Also tried the following:
settings: {
analysis: {
analyzer: {
name_analyzer: {
type: 'custom',
tokenizer: 'whitespace',
filter: ['test']
}
},
filter: {
test: {
type: 'word_delimiter',
preserve_original: true,
type_table: ['# => ALPHANUM']
}
}
}
}
but this only gets results for name:*#* and any other query doesn't work

Related

Kibana: vega-lite visualizations if data result is empty

I'm trying to create a vega-lite visualization with a query. But if the result of the query is return empty, I get the "cannot read property 'xx' undefined" message. Some part of my visualization code is below:
{
$schema: https://vega.github.io/schema/vega-lite/v2.6.0.json
data: {
name: our_data
url: {
index: index-7.0.1-index*
body: {
query: {
bool: {
filter: [
{
match_all: {}
}
{
match_all: {}
}
]
should: []
must_not: []
}
}
aggs: {
xx: {
top_hits: {
docvalue_fields: [
{
field: someField
format: use_field_mapping
}
]
_source: ["someField"]
size: 1
sort: [
{
#timestamp: {order: "desc"}
}
]
}
}
}
}
}
format: {property: "aggregations.xx.hits.hits"}
}
Is there any way not to get "cannot read property 'xx' undefined" message? I just want if there is no data result, vega-lite visualization looks blank.
Thank you.

MongoDB full text search, autocomplete on two fields

I am trying to implement MongoDB atlas search, and the objective is autocomplete on 2 fields.
I currently have this implementation:
const searchStep = {
$search: {
// Read more about compound here:
// https://docs.atlas.mongodb.com/reference/atlas-search/compound/
compound: {
must: [
{
autocomplete: {
query,
path: 'name',
},
},
{
autocomplete: {
query,
path: 'description',
},
},
],
},
},
}
This does not seem to work, seems to only work when there is both a match on the name AND description. How can I fix this, so I query for both name and description?
I now tried using the wildcard option:
{
wildcard: {
query,
path: ['name', 'description'],
allowAnalyzedField: true,
}
}
But the wildcard solution does not seem to work - no relevant results are returned...
If you are trying to match on name or subscription, use should: instead of must:
must will require that all of the subqueries match, where as should requires that only 1 of them does.
const searchStep = {
$search: {
// Read more about compound here:
// https://docs.atlas.mongodb.com/reference/atlas-search/compound/
compound: {
should: [
{
autocomplete: {
query,
path: 'name',
},
},
{
autocomplete: {
query,
path: 'description',
},
},
],
},
},
}

is there a way to write a boolean query with different conditions in elasticsearch?

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" ]

Elasticsearch edgeNGram analyzer/tokenizer fuzzy query matching

We have an Accounts table that we are searching for similar records using fuzzy query with edgeNGram analyzer for multiple fields. Our setup:
Settings
{
settings: {
analysis: {
analyzer: {
edge_n_gram_analyzer: {
tokenizer: "whitespace",
filter: ["lowercase", "ednge_gram_filter"]
}
},
filter: {
ednge_gram_filter: {
type: "edgeNGram",
min_gram: 2,
max_gram: 10
}
}
}
}
}
Mapping
{
mappings: {
document_type: {
properties: {
uid: {
type: "text",
analyzer: "edge_n_gram_analyzer"
},
shop_name: {
type: "text",
analyzer: "edge_n_gram_analyzer"
},
seller_name: {
type: "text",
analyzer: "edge_n_gram_analyzer"
},
...
...
...
locale_id: {
type: "integer"
}
}
}
}
}
Query
{
body: {
query: {
bool: {
must: [
{
bool: {
should: [
{
fuzzy: {
uid: {
value: "antonline",
boost: 1.0,
fuzziness: 2,
prefix_length: 0,
max_expansions: 100
}
}
},
{
fuzzy: {
seller_name: {
value: "antonline",
boost: 1.0,
fuzziness: 2,
prefix_length: 0,
max_expansions: 100
}
}
},
{
fuzzy: {
shop_name: {
value: "antonline",
boost: 1.0,
fuzziness: 2,
prefix_length: 0,
max_expansions: 100
}
}
}
]
}
}
],
must_not: [
{
term: {
locale_id: {
value: 7
}
}
}
]
}
}
}
}
The above example finds different variations of 'antonline' string such as "antonline", "sanjonline", "tanonline", "kotonline", "htonline", "awmonline". However, it doesn't match strings with punctuation like antonline.com or even antonlinecom without the dot. We tried different types of tokenizers but nothing helps.
How could we achieve the search result as we expect?
I resolved that issue by removing everything that matches this regex:
[.,'\"\-+:~\^!?*\\]
Do the removal while building the index as well as while searching.

Multiple types in Elasticsearch Type Filter

I have a filtered query like this
query: {
filtered: {
query: {
bool: {
should: [{multi_match: {
query: #query,
fields: ['title', 'content']
}
},{fuzzy: {
content: {
value: #query,
min_similarity: '1d',
}
}}]
}
},
filter: {
and: [
type: {
value: #type
}]
}}}
That works fine if #type is a string, but does not work if #type is an array. How can I search for multiple types?
This worked, but I'm not happy with it:
filter: {
or: [
{ type: { value: 'blog'} },
{ type: { value: 'category'} },
{ type: { value: 'miscellaneous'} }
]
}
I'd love to accept a better answer
You can easily specify multiple types in your search request's URL, e.g. http://localhost:9200/twitter/tweet,user/_search, or with type in the header if using _msearch, as documented here.
These are then added as filters for you by Elasticsearch.
Also, you usually want to be using bool to combine filters, for reasons described in this article: all about elasticsearch filter bitsets
This worked for me:
Within the filter parameter, wrap multiple type queries as should clauses for a bool query
e.g
{
"query": {
"bool": {
"must": {
"term": { "foo": "bar" }
},
"filter": {
"bool": {
"should": [
{ "type": { "value": "myType" } },
{ "type": { "value": "myOtherType" } }
]
}
}
}
}
}
Suggested by dadoonet in the Elasticsearch github issue Support multiple types in Type Query

Resources