Opensearch client, search without using a model - c#

i'm using Opensearch Client .NET implementation. The only way to use the search method is to map the response to a model like in this way
await client.SearchAsync<Model>(e => e
.Index("index")
.From(0)
.Size(1)
.Query(q => q
.Bool(b => b
.Must(
m => m.Term(t => t.Field(f => f.modelField).Value("somevalue")),
))));
If i try to use something like dynamic or Dictionary i get an error with message:
"message": "'capacity' must be greater than zero. (Parameter 'capacity')",
Is possible to map the response to a dictionary?
Thanks to all

Related

ElasticSearch NEST OR query

i've been having some trouble regarding creating a query that searches through different fields.
I got the answers i wanted by creating several queries - but for the sake of performance - i want to do this in just one query, if possible.
I've tried setting the query up in several .Should clauses, but it seems that it searches for documents that matches every field, which i think is intended.
It looks like this;
.From(0)
.Sort(sort => sort
.Field("priority", SortOrder.Descending))
.Sort(sort => sort
.Ascending(a => a.ItemNumber.Suffix("keyword")))
.Sort(sort => sort
.Descending(SortSpecialField.Score))
.TrackScores(true)
.Size(25)
.Query(qe => qe
.Bool(b => b
.Should(m => m
.Match(ma => ma
.Boost(1.1)
.Field("itemnumber")
.Query(ItemNumber)
))
.Should(m => m
.Match(ma => ma
.Boost(1.1)
.Field("itemnumber2")
.Query(ItemNumber)))
.Should(m => m
.Match(ma => ma
.Boost(1.1)
.Field("ean")
.Query(ItemNumber)))
.Should(m => m
.Match(ma => ma
.Boost(1.1)
.Field("itemalias")
.Query(ItemNumber)))
)));
What i want it to do is; Search through the Itemnumber and see if a document matches, if not, search through the Itemnumber2 and so on.
Is there an efficient way to do this in just one query?
I believe the syntax for a should query with multiple parts should be an array of queries. Your way you would just add multiple separate should queries. What you want should probably look like this:
.Bool(b => b
.Should(
m => m
.Match(ma => ma
.Boost(1.1)
.Field("itemnumber")
.Query(ItemNumber)),
m => m
.Match(ma => ma
.Boost(1.1)
.Field("itemnumber2")
.Query(ItemNumber)),
m => m
.Match(ma => ma
.Boost(1.1)
.Field("ean")
.Query(ItemNumber)),
m => m
.Match(ma => ma
.Boost(1.1)
.Field("itemalias")
.Query(ItemNumber)))
More here
Have you tried using a MultiMatch query instead? https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html
This would allow you to search your documents as you would with a Match query, but you should be able to specify multiple fields to search in.
This would allow you to ditch the bool query.

Dicionary intersect keys with list and get in result dicionary with values at the beggining LINQ

I have a problem I cant make a Linq query which intersect my dictionary keys with list, and back to the origin dictionray without this which are gone.
var gg = request
.Number_Name
.Keys
.Intersect(_context.Users.Select(x => x.Phone))
.ToDictionary(t => t);
I tried something like this, but it doesnt work.
try this code :
1 - Get keys
var keys = request
.Number_Name
.Keys
.Intersect(_context.Users.Select(x => x.Phone));
2 - Get new dictionary
var newDic = request
.Number_Name
.Where(k => keys.Contains(k.Key))
.ToDictionary(k => k.Key, v => v.Value);
Or
var newDic = request
.Number_Name
.Keys
.Intersect(_context.Users.Select(x => x.Phone))
.ToDictionary(k => k, v => request.Number_Name[v]);

Performance of .Include in LINQ

Which one is more efficient considering speed?
This one:
var studentWithBatchName =
db.Student.AsNoTracking()
.Include(c => c.Department)
.Include(c => c.Department.Section)
.Include(c => c.Department.Section.Batch)
.Select(c => c.Name, c.Department.Section.Batch.Name);
or this one:
var studentWithBatchName =
db.Student.AsNoTracking()
.Include(c => c.Department.Section.Batch)
.Select(c => c.Name, c.Department.Section.Batch.Name);
The Include statement is just getting the data from the related datasources/tables. If you are saying Include(c => c.Department.Section.Batch) you get the .Department.Section.Batch values.
If you are using .Include(c => c.Department).Include(c => c.Department.Section).Include(c => c.Department.Section.Batch)
it would theoretically add 3 joins to the query. I don't know if .NET catches these circumstances, but I would consider using ONLY Include(c => c.Department.Section.Batch) when you only need this value.
Found .ProjectTo to be more efficient considering speed. Instead of using Include which acts like outer join and makes your query big putting load on the server one can use .ProjectTo<>
Can get .ProjectTo<> by
using AutoMapper.QueryableExtensions;
Eg. var response = await db.TableName.ProjectTo().ToListAsync();

Elastic Search - Reverse match query

Currently I wrote a query against an elastic server to remove all documents with an old "BatchVersion". After thinking about it, to be safe, I want all records delete that don't equal the current "BatchVersion". Here is my current code
_client.DeleteByQuery<Data.ElasticSearch.Employee>(s => s
.Index(indexName)
.Size(1000)
.Query(q => q.
Bool(b => b.
MustNot(mn => mn.
Match(m => m.Field("BatchVersion").
Query([newVersionId]))))));
When the code is run, no records are deleted. Any ideas?
I had to use Default_Field for it to work. I used kibana to figure it out.
_client.DeleteByQuery<Employee>(s => s
.Index(indexName)
.Size(1000)
.Query(q => q.
Bool(b => b.
MustNot(mn => mn.
QueryString(qs => qs.DefaultField("batchVersion").Query(newVersionId.ToString()))))));

Elasticsearch NEST

Currently I started using Elasticsearch wrapper for c# "NEST", and I'm facing some troubles for writing queries that check for partial similarities such as in "book" and "books", so when I have a document that contains "books", if I search for "book" it doesn't find it:
here is my code :
var articles = client.Search<ProductResult>(s => s
.From(0)
.Size(1000)
.MatchAll()
.Query(q => q.QueryString(d => d
.Query(query)
)));
Try analyzing your fields with a stemming analyzer like snowball which will try it's best to reduce words to their root form. For example, books and booking => book, jumps and jumping => jump. etc... The algorithm behind it isn't perfect and will trip up on irregular words/plural forms, but for the most part it works very well (on most European languages).
You can apply different analyzers when you initially create your index, or on an existing index using the update mapping API. Either way, you'll have to reindex our documents to apply the new analysis.
Create index example using NEST:
client.CreateIndex("yourindex", c => c
...
.AddMapping<YourType>(m => m
.MapFromAttributes()
.Properties(ps => ps
.String(s => s.Name("fieldname").Analyzer("snowball"))
...
)
)
);
Update mapping example:
client.Map<YourType>(m => m
.MapFromAttributes()
.Index("yourindex")
.Properties(ps => ps
.String(s => s.Name("fieldname").Analyzer("snowball"))
...
)
);
Here's some really great info on algorithmic stemmers in The Definitive Guide.
U can use Fuzzy also...
var articles = client.Search<ProductResult>(s => s
.From(0)
.Size(1000)
.Query(q => q.(d => d
.Fuzzy(fz => fz.OnField("field").Value("book").MaxExpansions(2))
));

Categories

Resources