I have two records for the same customer but with different customerLastUpdated dates, there is a way to return only the most recent one?
var response = await this.client.SearchAsync<ElasticCustomer>(searchDescriptor => searchDescriptor
.AllTypes()
.Query(q => q.Bool(b => b
.Should(
sh => sh.Match(m => m.Field(f => f.CustomerName).Query(query)),
sh => sh.Wildcard(w => w.Field(f => f.MobileNumber.Suffix("keyword")).Value($"*{query}*")))));
Related
I written my NEST query like below
var searchResponse = await _elasticClient.SearchAsync<T>(s => s
.Index(indexName)
.Query(q => q
.Bool(b => b
.Should(
sh => sh.Prefix(pr => pr.Field(fieldNames[0]).Value(fieldValues[0])),
sh => sh.Prefix(pr => pr.Field(fieldNames[1]).Value(fieldValues[1]))
)
))
.Aggregations(ag=>ag.Cardinality(sumName,ca=>ca.Field(cardinalField)))
.Collapse(co=>co.Field(cardinalField))
).ConfigureAwait(false);
return searchResponse.Count;
}
I need to iterate below code
sh => sh.Prefix(pr => pr.Field(fieldNames[0]).Value(fieldValues[0])),
sh => sh.Prefix(pr => pr.Field(fieldNames[1]).Value(fieldValues[1]))
as per input array
I tried like below
private static QueryContainer MatchAny<T>(QueryContainerDescriptor<T> descriptor, Field[] fields, string value) where T : class
{
QueryContainer q = new QueryContainer();
for (int i=0;i<=fields.Length-1;i++)
{
q |= descriptor.Match(t => t.Field(fields[i]).Query(value));
}
return q;
}
var searchResponse = await _elasticClient.SearchAsync<T>(s => s
.Index(indexName)
.Query(q => q
.Bool(b => b
.Should(sh=> MatchAny(sh, fieldNames, fieldValue)
)
))
).ConfigureAwait(false);
but getting compile error :
cannot convert from 'string[]' to 'Nest.Field[]'
so how to iterate fields as per coming no of inputs in NEST queries ?
I am developing something to show a pie chart of the users' age with slicing them as
0-17
18-34
35-44
44-54
55+
Not Available
here i am getting the ages based on the date range;
var aggaResonse = client.Search<JSModel>(a => a
.Size(0)
.Query(q => q.Bool(b => b.Must(m => m
.DateRange(date => date
.Field(p => p.CreatedDate)
.GreaterThanOrEquals(start)
.LessThanOrEquals(end)),
m =>
m.Term(t => t.Field(f => f.StepType.Suffix("keyword")).Value("User"))
)
))
.Aggregations(c => c.DateRange(nameof(AgeModel), x => x
.Field(f => f.BirthDate)
.Ranges(r => r.From(DateMath.Now.Subtract("17y")).To(DateMath.Now).Key(nameof(result.Years_0_17)),
r => r.From(DateMath.Now.Subtract("34y")).To(DateMath.Now.Subtract("18y")).Key(nameof(result.Years_18_34)),
r => r.From(DateMath.Now.Subtract("44y")).To(DateMath.Now.Subtract("35y")).Key(nameof(result.Years_35_44)),
r => r.From(DateMath.Now.Subtract("54y")).To(DateMath.Now.Subtract("45y")).Key(nameof(result.Years_45_54)),
r => r.From(DateMath.Now.Subtract("120y")).To(DateMath.Now.Subtract("55y")).Key(nameof(result.Years_55_Plus))
)
)
));
if (!aggaResonse.IsValid)
return result;
result.Years_0_17 = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_0_17)).DocCount;
result.Years_18_34 = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_18_34)).DocCount;
result.Years_35_44 = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_35_44)).DocCount;
result.Years_45_54 = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_45_54)).DocCount;
result.Years_55_Plus = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_55_Plus)).DocCount;
return result;
what i need is to have a "Not Available" slice for users who has NULL as birthdate with mapping it as;
result.Not_Available = ....;
Any suggestions with following best practices for nested NEST aggs ?
I was thinking to run another search which i guess it's not the best practice.
After digging documentations too much, here is the solution i wrote;
I added a "Missing" attribute to the current aggregation;
&& c.Missing("DOBMissing", x => x.Field(f => f.BirthDate))
So it became like;
.Aggregations(c => c.DateRange(nameof(AgeModel), x => x
.Field(f => f.BirthDate)
.Ranges(r => r.From(DateMath.Now.Subtract("17y")).To(DateMath.Now).Key(nameof(result.Years_0_17)),
r => r.From(DateMath.Now.Subtract("34y")).To(DateMath.Now.Subtract("18y")).Key(nameof(result.Years_18_34)),
r => r.From(DateMath.Now.Subtract("44y")).To(DateMath.Now.Subtract("35y")).Key(nameof(result.Years_35_44)),
r => r.From(DateMath.Now.Subtract("54y")).To(DateMath.Now.Subtract("45y")).Key(nameof(result.Years_45_54)),
r => r.From(DateMath.Now.Subtract("120y")).To(DateMath.Now.Subtract("55y")).Key(nameof(result.Years_55_Plus))
)
) &&
c.Missing("DOBMissing", x => x.Field(f => f.BirthDate))
)
And i'd accessed the "missing" part of aggregation as following;
result.Not_Available = aggaResponse.Aggregations.Missing("DOBMissing").DocCount;
Hey I am trying to query and find a object that looks something like this:
I have already result
I have id that is quiz id.
So i have both Ids.
var singlequiz = await _context.Quizzes
.Include(q => q.Questions)
.ThenInclude(question => question.Options)
.Include(qz => qz.Results)
.Where(b => b.Id == id)
.Select(c => c.Results.Select(z => z.Id == result.Id))
.FirstOrDefaultAsync();
What I am trying to do here is : find an object with id X, then that object with id X has a list of results, I want to get the list, BUT with only the one element that has id of result.Id.
What am i doing wrong?
EDIT:
Used this ATM
var singlequiz = await _context.Quizzes
.Include(x => x.Questions)
.ThenInclude(x => x.Options)
.Include(x => x.Results)
.FirstOrDefaultAsync(x => x.Id == id);
var singleQuizElement = singlequiz.Results.Where(x => x.Id == result.Id).ToList();
singlequiz.Results = singleQuizElement;
Try this :
var singlequiz = await _context.Quizzes
.Include(x => x.Questions)
.ThenInclude(x => x.Options)
.Include(x => x.Results)
.FirstOrDefaultAsync(x=> x.Id == id && x.Results.Any(y => y.Id == result.Id));
Query logic is Grouping the items by Id and Ordering it by Id. Then inside grouped items Ordering by Item1 then by Item2.
Linq query below,
var group1Items = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code = 1)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items).ToList();
var group2Items = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code = 2)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items).ToList();
MyList.Clear();
MyList.InsertRange(Mylist.Count, group1Items);
MyList.InsertRange(Mylist.Count, group2Items);
In the above two queries, only difference is Where condition. Is it possible to rewrite into single query?
Single query:
var groupItems = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code == 1 || a.Code == 2)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items).ToList();
If Code 1 must come before Code 2:
var groupItems = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code == 1)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items)
.Union(MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code == 2)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items)).ToList();
If you only want to avoid code duplication it may be easiest to capture a variable holding the code by which to filter.
int code = 0; // initialize with any value
var groupItems = MyList.GroupBy(g => g.Id)
.Where(w => w.Any(a => a.Code == code)
.Select(s => new
{
key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
})
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items); // No ToList() here!
MyList.Clear();
code = 1;
MyList.InsertRange(Mylist.Count, groupItems.ToList());
code = 2;
MyList.InsertRange(Mylist.Count, groupItems.ToList());
Removed where clause in the LINQ expression and implemented at InsertRange() method. This avoids redundant queries
var groupItems = MyList
.GroupBy(g => g.Id)
.Select(s => new
{ key = s.Key,
items = s.OrderBy(o => o.Item1)
.ThenBy(t => t.Item2)
}
)
.OrderBy(o => o.Id)
.SelectMany(sm => sm.Items).ToList();
MyList.Clear();
MyList.InsertRange(Mylist.Count, groupItems.Where(w => w.Code == 1));
MyList.InsertRange(Mylist.Count, groupItems.Where(w => w.Code == 2));
I have a counterpart, which has an address, which MIGHT have a country assigned.
How do I handle this:
InvoiceAddress invoiceAddres = null;
Country InvoiceAddressCountry = null;
Counterpart counterpart = null;
CounterpartTabDTO result = null;
// projections for DTO-mapping
var projections = new[]
{
Projections.Property(() => counterpart.CounterpartId).WithAlias(() => result.InternalID),
Projections.Property(() => counterpart.GlobalCounterpartId).WithAlias(() => result.BasicInfo_GlobalCounterpartyID),
Projections.Property(() => counterpart.Name).WithAlias(() => result.BasicInfo_Name),
Projections.Property(() => counterpart.ShortName).WithAlias(() => result.BasicInfo_ShortName),
Projections.Property(() => counterpart.PhoneNumber).WithAlias(() => result.BasicInfo_Telephone),
Projections.Property(() => counterpart.Webpage).WithAlias(() => result.BasicInfo_WWW),
Projections.Property(() => counterpart.Language).WithAlias(() => result.BasicInfo_Language),
Projections.Property(() => counterpart.VAT).WithAlias(() => result.BasicInfo_VAT),
Projections.Property(() => counterpart.CompanyRegistrationNumber).WithAlias(() => result.BasicInfo_CompanyRegistationno),
Projections.Property(() => invoiceAddres.Name).WithAlias(() => result.BasicInfo_InvoiceAddressContactPerson),
Projections.Property(() => invoiceAddres.Street).WithAlias(() => result.BasicInfo_InvoiceAddressAddress),
Projections.Property(() => invoiceAddres.PostalCode).WithAlias(() => result.BasicInfo_InvoiceAddressPostalCode),
Projections.Property(() => invoiceAddres.City).WithAlias(() => result.BasicInfo_InvoiceAddressCity),
Projections.Property(() => invoiceAddres.Area).WithAlias(() => result.BasicInfo_InvoiceAddressArea),
Projections.Property(() => InvoiceAddressCountry.PrintableName).WithAlias(() => result.BasicInfo_InvoiceAddressCountry),
Projections.Property(() => invoiceAddres.Department).WithAlias(() => result.BasicInfo_InvoiceAddressDepartment),
Projections.Property(() => invoiceAddres.Fax).WithAlias(() => result.BasicInfo_InvoiceAddressFax),
Projections.Property(() => invoiceAddres.MainEmail).WithAlias(() => result.BasicInfo_InvoiceAddressEmail),
};
var query = Session.QueryOver(() => counterpart)
.JoinQueryOver<InvoiceAddress>(x => x.InvoiceAddresses, () => invoiceAddres)
.Where(x => x.IsDefault)
.JoinQueryOver<Country>(() => invoiceAddres.Country, () => InvoiceAddressCountry)
.Select(projections);
The issue is InvoiceAddressCountry, which might be null. If that happens, I'd like the result.BasicInfo_InvoiceAddressCountry property stays null.
To clarify, the above code does not work. It can't handle the null.
From your words I can suppose that you'll need to use left join:
.Left.JoinQueryOver(() => invoiceAddres.Country, () => InvoiceAddressCountry)