Elasticsearch return distinct property values - elasticsearch

I have collection of Products with property Brand and 2 unique values:
"Super brand A"
"Super brand B"
ES query
var response = new ElasticClient().Search<DTO>(s => s
.Index("index")
.Type("type")
.Aggregations(a => a
.Terms("unique", t => t
.Field(f => f.Brand)
//.Field(f => f.Brand.Suffix("keyword"))
.Size(1000)
)
)
);
var brands = (((BucketAggregate)response.Aggregations.First().Value).Items).Cast<KeyedBucket<Object>>().Select(x => x.Key).ToList();
ES returns 4 invalid values
"Super"
"brand"
"A"
"B"
I've tried to force full property match by adding .Suffix("keyword") to field but then it returns empty list. How can I get 2 distinct values?

Related

Elasticsearch NEST API, Searching Multiple Indices

If one is seraching several indexes at the same time, is there any way to say that if searching index A, then add this filter and if searching index B then add a different filter.
For example:
var filters = new List<Func<QueryContainerDescriptor<PropertySearchResult>, QueryContainer>>();
filters.Add(fq => fq.Term(t => t.Field(f => f.PromoterId).Value(user.Id)));
filters.Add(fq => fq.Term(t => t.Field(f => f.SubscriptionId).Value(subscriptionId)));
string indicies = String.Join(",", Utils.SupportedCountries.Select(c => c.Key.ToLower()).ToArray());
var result = await ElasticSearchConfig.GetClient().DeleteByQueryAsync<PropertySearchResult>(u => u
.Index(indicies)
.Query(q => q
.Bool(bq => bq.Filter(filters))));
at the moment, all indices will be subject to the same filters but I would like to vary the filters based on which index is being searched.
Add(with &&) a term query to each of your filters
.Term("_index", A)
Check this link
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-index-field.html

ElasticSearch Nest: Can only use prefix queries on keyword and text fields - not on which is of type float

Searching values in multiple fields is not working when search text contains space. For example if i search for value "price" than i get results but if i search for "price level" than i get following error:
Can only use prefix queries on keyword and text fields - not on which
is of type float
I have one date field and one float field in indexed documents. And error is thrown because of this fields.
Following is my code of creating Index:
var createIndexResponse = client.CreateIndex("messages", c => c.Settings(s => s.NumberOfShards(1).NumberOfReplicas(0).Analysis(a => a.Analyzers(anl => anl.Custom("default", ca => ca.Tokenizer("whitespace").Filters(new List<string>() { "lowercase" }))))).Mappings(ms => ms.Map<Object>(m => m.Properties(p => p.Number(s => s.Name("id").Index(false)).Text(s => s.Name("displaytext").Index(false)).Text(s => s.Name("text").Index(false)).Text(s => s.Name("url").Index(false)).Date(d => d.Name("Search_ReceivedOn"))))));
Following is my search query:
Dim funcMust = New List(Of Func(Of Nest.QueryContainerDescriptor(Of Object), Nest.QueryContainer))()
funcMust.Add(Function(sh) sh.Term("From", UserID) Or sh.Term("To", UserID))
Dim resp = client.Search(Of Object)(Function(s) s.Index("messages").IgnoreUnavailable(True) _
.Query(Function(qry) qry.QueryString(Function(qs) qs.Fields("Search_*").Query(searchText).DefaultOperator(Nest.Operator.And))) _
.PostFilter(Function(pf) pf.Bool(Function(b) b.Must(funcMust))).From((pageIndex - 1) * pageSize).Take(pageSize).Source(Function(x) x.Includes(Function(f) f.Fields(fields))))
I have dynamic columns in indexed document so i can not use term queries with exact field names. Is there any way to search on all fields that starts with "Search_" without error i have mentioned above?
In my case this occurred when i perform search with spacial character.
I fixed this with following,
Elasticsearch - v6.8.6
Map<String, Float> fields = new HashMap<>();
fields.put("content.keyword", 1f);
fields.put("name.keyword", 2f);
fields.put("tag.keyword", 3f);
SimpleQueryStringBuilder queryBuilder = new SimpleQueryStringBuilder(searchQuery);
queryBuilder.fields(fields);
queryBuilder.analyzeWildcard(Boolean.TRUE);

Select specific field in MongoDB using ruby then pass the value to a variable

I'm working on a script that will return value in a specific field and exclude other fields i tried these codes:
name = 'bierc'
puts collection.find({"name"=> name},{:fields => { "_id" => 0}}).to_a
and
name = 'bierc'
collection.find("name" => name,"_id" => 0).each{|row| puts row.inspect}
These two returns
{"_id"=>BSON::ObjectId('55f0d965fcd4fe1c659cf472'), "name"=>"bierc", "song"=>"testsong"}
I want to select name only and exclude the song and especially the _id then will work on to pass the value of name field to a variable.
The option is not fields but projection. You do need _id => 0 but then 1 for any field or fields you do want to select should exclude the others.
collection.find("name" => name, projection: => { "_id" => 0, "name" => 1}})

ElasticSearch in e-commerce: multiple categories for a product

How do you index products like that in ElasticSearch? We've separated all documents based on the attributes (colour, brand, size, whatever users input), but all of them belong to a set of categories. May be one, may be 15.
[0] => Array
(
[product_id] => 123456
[product_name] => Shirt 1
[filter_name] => Colour
[filter_value] => Blue
[product_parent_id] => 111111
[product_has_discount] => 0
[product_price] => 19.99
[product_stock] => 1
)
[1] => Array
(
[product_id] => 123457
[product_name] => Shirt 1
[filter_name] => Colour
[filter_value] => Red
[product_parent_id] => 111111
[product_has_discount] => 0
[product_price] => 19.99
[product_stock] => 1
)
How would we tag categories into this? Would it be so simple as saying
[product_categories] => ;4750;4834;4835;4836;
And then querying ElasticSearch with match against category with the value ;4836;? Is that possible? Recommended?
You can define product_categories as integer in your mapping and pass in the category values as array like
[product_categories] => array(4750,4834,4835,4836)
EDIT: You read more about mapping here. A more specific to mapping an array type.
Once your data is indexed like that you can query, filter, aggregate on the field product_categories easily in all combinations.
for example to match products in category 4750 or 4750:
{
"filter": {
"terms": {
"product_categories": [
4750,
4750
]
}
}
}

Pivot in LINQ using lambda expression

I am writing a lambda in linq for getting the pivoted data from the resulting list.For getting the pivoting columns am setting a where condion to get the value.the problem here is am getting default value if the where condtion fails.I dont want the column if the where condition fails.Kindly help me out.
var query = dataList
.GroupBy(c => c.IpAddress)
.Select(g => new
{
IPAddress = g.Key,
AssetType = g.ElementAtOrDefault(0).AssetTypeName,
AssetName = g.ElementAtOrDefault(0).AssetName,
//if where condition fails i dont need this column.
//also am giving c.DsName == "Active Calls" ,how to achieve tis dynamically
**ActiveCalls = g.Where(c => c.DsName == "Active Calls").Sum(c => c.CurrentValue),**
**HoldCalls = g.Where(c => c.DsName == "Hold Calls").Sum(c => c.CurrentValue),**
**CPU = g.Where(c => c.DsName == "CPU").Sum(c => c.CurrentValue),**
});
Why not just create a value to hold the sum and then specify its a type in another column. That way you don't have to deal with null columns. (The assumption is that only one type is valid at a time).
Value = g.Sum(c => c.CurrentValue), // Value as specified by the the DsName property.
DsName = c.DsName

Resources