Elastic search filter using query string - elasticsearch

Using Query string OnFieldWithBoosts added different fields need to apply filter, string fields records are working fine.
For id field when I include .Add(id,2) it does not return ID based result.
When I use term then ID fields records working fine.
Now in the query section,
I have used OR condition, so when first condition satisfies, it does not check second one.
If I user AND condition, then it checks for both the condition matches.
But I need first query results and second query results concat into one result
CODE:
var result = client.Search<dynamic>(q => q
.Indices("test")
.Types("user")
.From(1)
.Size(10)
.MinScore(1.0)
.Fields("id", "createddate", "email", "modifieddate", "name", "companyname") // Result set Fields Fields
.Query(q1 =>
{
qq = (q1.ConstantScore(a => a.Filter(b => b.Term("id", searchKeyword))))
|| q1.QueryString(qs => qs.Query(searchKeyword).OnFieldsWithBoost(a => a.Add("notes",3).Add("email", 2).Add("name", 2)));
return qq;
})
);

Related

Running DateRange with null values on ElasticSearch?

I am writing some queries in my ElasticSearch project that can be filtered by Date. I have written them like this:
var searchResponse = client.Search<mdl.Event>(s => s
.Query(q => q
.QueryString(qs => qs
.Query(search.Space))
&& q
.DateRange(r => r
.Field(f => f.CreatedTimeStamp)
.GreaterThanOrEquals(search.From)
.LessThanOrEquals(search.To))));
However, search.From and search.To are optional inputs, so they might turn out to be null. In the event that they are null, does this break the query? Or will it continue as if the DateRange part of the query is not included?
Nest queries are condition less. If input is determined to be null or empty string then the query will be omitted from the request.
So you don't need to check whether each filter property is null , NEST will perform this filtering by default.
In your case if search.From and search.To are null then range check will be removed from final query

Linq query to select all records that have sub records that match all values in an array of values?

I have a table that contains records that have a related table that may have multiple records for each of the main records. This is a table of flags.
i.e.
MyRecord can have multiple subrecords Flag1, Flag4, Flag7
I am trying to create a Linq query that will return records that have all the flags I specify.
This is code of what I am trying to do
var flags = new List<string>() { "Flag1"};
db.Contents.Include(f=>f.Flags)
.Where(a => flags.All(b=>a.Flags.Any(f =>f.Name==b)));
The above almost works but returns records with Flag1 along with records that have Flag1,Flag4 and Flag1,Flag4,Flag7. I need to return only records that have the requested flags set.
var answer = db.Contents.Include(x => x.Flags)
.Where(x =>
x.Flags.Select(y => y.Name).Distinct().Count() == flags.Count
&&
flags.All(y => x.Flags.Any(z => z.Name == y)))
.ToList();

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 from multiple tables based upon search term but good in performance

I have a query in which I pass the search term to filter the list of Companies, either by Email or company Title which is stored in another table (TranslationTexts) as Text column for multiple locales.
The query runs fine but it is very heavy and takes time. How can I make it more efficient?
See Table Diagram Image
The query:
gm.ListData = context.Companies.ToList()
.Where(a => a.AspNetUser.Email.NullableContains(searchTerm) ||
a.TitleTranslation.TranslationTexts
.Where(b => b.Text.NullableContains(searchTerm)).Any()
).Select(c => new ListCompany
{
CompanyID = c.CompanyID,
EmailID = c.AspNetUser.Email,
Title = c.TitleTranslation.TranslationTexts.FirstOrDefault(d => d.Locale == Locale).Text
}).ToList();

dynamic asc desc sort

I am trying to create table headers that sort during a back end call in nhibernate. When clicking the header it sends a string indicating what to sort by (ie "Name", "NameDesc") and sending it to the db call.
The db can get quite large so I also have back end filters and pagination built into reduce the size of the retrieved data and therefore the orderby needs to happen before or at the same time as the filters and skip and take to avoid ordering the smaller data. Here is an example of the QueryOver call:
IList<Event> s =
session.QueryOver<Event>(() => #eventAlias)
.Fetch(#event => #event.FiscalYear).Eager
.JoinQueryOver(() => #eventAlias.FiscalYear, () => fyAlias, JoinType.InnerJoin, Restrictions.On(() => fyAlias.Id).IsIn(_years))
.Where(() => !#eventAlias.IsDeleted);
.OrderBy(() => fyAlias.RefCode).Asc
.ThenBy(() => #eventAlias.Name).Asc
.Skip(numberOfRecordsToSkip)
.Take(numberOfRecordsInPage)
.List();
How can I accomplish this?
One way how to achieve this (one of many, because you can also use some fully-typed filter object etc or some query builder) could be like this draft:
Part one and two:
// I. a reference to our query
var query = session.QueryOver<Event>(() => #eventAlias);
// II. join, filter... whatever needed
query
.Fetch(#event => #event.FiscalYear).Eager
var joinQuery = query
.JoinQueryOver(...)
.Where(() => !#eventAlias.IsDeleted)
...
Part three:
// III. Order BY
// Assume we have a list of strings (passed from a UI client)
// here represented by these two values
var sortBy = new List<string> {"Name", "CodeDesc"};
// first, have a reference for the OrderBuilder
IQueryOverOrderBuilder<Event, Event> order = null;
// iterate the list
foreach (var sortProperty in sortBy)
{
// use Desc or Asc?
var useDesc = sortProperty.EndsWith("Desc");
// Clean the property name
var name = useDesc
? sortProperty.Remove(sortProperty.Length - 4, 4)
: sortProperty;
// Build the ORDER
order = order == null
? query.OrderBy(Projections.Property(name))
: query.ThenBy(Projections.Property(name))
;
// use DESC or ASC
query = useDesc ? order.Desc : order.Asc;
}
Finally the results:
// IV. back to query... call the DB and get the result
IList<Event> s = query
.List<Event>();
This draft is ready to do sorting on top of the root query. You can also extend that to be able to add some order statements to joinQuery (e.g. if the string is "FiscalYear.MonthDesc"). The logic would be similar, but built around the joinQuery (see at the part one)

Resources