Calculate sum based on nested filter - c#

The problem
This works as expected and produces the result with the totalpax field being correct. However, the pax field for each destination, should be the sum based on the destination Id.
Code
public async Task<IEnumerable<ReservationCalendarGroupVM>> GetForCalendarAsync(string fromDate, string toDate) {
return await context.Schedules
.AsNoTracking()
.Where(x => x.Date >= Convert.ToDateTime(fromDate) && x.Date <= Convert.ToDateTime(toDate))
.GroupBy(z => new { z.Date })
.Select(e => new ReservationCalendarGroupVM {
Date = e.Key.Date.ToString(),
Destinations = e.GroupBy(i => new { i.Destination.Id, i.Destination.Abbreviation, i.Destination.Description }).Select(p => new DestinationCalendarVM {
Id = p.Key.Id,
Abbreviation = p.Key.Abbreviation,
Description = p.Key.Description,
Pax = context.Reservations.Where(y => y.Date == e.Key.Date).Sum(h => h.TotalPersons)
}),
TotalPax = context.Reservations.Where(y => y.Date == e.Key.Date).Sum(h => h.TotalPersons).ToListAsync();
}
Result
"date": "2022-07-02",
"destinations": [
{
"id": 1,
"description": "PAXOS - ANTIPAXOS",
"abbreviation": "PA",
"pax": 254
},
{
"id": 3,
"description": "BLUE LAGOON",
"abbreviation": "BL",
"pax": 254
}
],
"totalpax": 432

I believe the problem lies in this line:
Pax = context.Reservations.Where(y => y.Date == e.Key.Date).Sum(h => h.TotalPersons)
You're filtering exclusively by Date, but you need to filter simultaneously by Destination. As you didn't share the models it's not very easy to infer, but I believe you'll need to do the following:
Pax = context.Reservations
.Where(y => y.Date == e.Key.Date && y.Destination.Id == e.Key.Id).Sum(h => h.TotalPersons)

Related

how i get list of one week data with count and date

I have try to get list of data for last on week date with count .the problem is if the count zero the date not in that list but i want all seven days with count
lastWeekRegisterStatistic1 = dbContext.MtMUsers.Join(dbContext.MtLogRegistrationAudits,
U => U.EmployeeId,
Ru => Ru.UserId,
(U, Ru) => new { U = U, Ru = Ru })
.Where(x => x.Ru.Status != null &&
x.Ru.Status.ToLower() == "success" &&
x.Ru.LoggedDate.Value.Date >= dt.Date &&
x.Ru.LoggedDate.Value.Date <= dt.AddDays(6).Date &&
x.U.IsMobileUser != 0 &&
(request.clientIds == null ||
request.clientIds.Count == 0 ||
request.clientIds.Contains(x.U.ClientId)) &&
(request.assetIds == null ||
request.assetIds.Count == 0 ||
request.assetIds.Contains(x.U.AssetId)) &&
((request.startDate == null && request.endDate == null) ||
(request.startDate <= x.U.CreatedDate && request.endDate >= x.U.CreatedDate)))
.GroupBy(g => new { g.Ru.LoggedDate.Value.Date }).OrderByDescending(o => o.Count())
.Select(s => new lastWeekStatisticsObject
{
date = s.Key.Date,
userCount = s.Count()
}).OrderBy(o => o.date).ToList();
this is my code
result is
"lastWeekStatistics": [
{
"date": "2022-11-10T00:00:00",
"userCount": 166
},
{
"date": "2022-11-11T00:00:00",
"userCount": 132
},
{
"date": "2022-11-12T00:00:00",
"userCount": 17
}
I only get three date data because balance date don't have data
I want all the seven days with date and count
Can't you just append the non-existing dates after the query manifested as List?
var emptyDates = Enumerable.Range(0, 6)
.Select(x => dt.Date.AddDays(x))
.Where(x =>
!lastWeekRegisterStatistic1
.Select(y => y.date)
.Contains(x))
.Select(x => new lastWeekStatisticsObject()
{
date = x,
userCount = 0
});
Then you can append the result using normal List operation:
lastWeekRegisterStatistic1.Add(emptyDates);
Don't forget to sort the List though!

Get summation of all field in mongodb c#

I have a mongodb which looks like this
[
{
"client_id": "abc",
"product_id": "123",
"weight": {
"value": 100
"unit": "kg"
}
},
{
"client_id": "def",
"product_id": "456",
"weight": {
"value": 200
"unit": "kg"
}
}
]
I need to get summation of weight value for a certain client id and product id using mongodb c# client, how can I do that?
I tried this but it is always returning 0
var total_weight = await Collection.AsQueryable()
.Where(
x => x.client_id == "abc" &&
x => x.product_id== "123")
.SumAsync(x => x.weight.value);
Thanks
I think you are looking for this query so you can try this code:
var total_weight = await Collection.AsQueryable<YourModel>()
.Where(x => x.client_id == "abc" && x.product_id == "123")
.GroupBy(x => new { x.client_id, x.product_id })
.Select(x => x.Sum(y => y.weight.value))
.FirstOrDefaultAsync();

why .Select or .ToList() is giving Nested JSON while .Count is comming in parent JSON?

all three(Attendance,InTime,OutTime ) are coming from the referenced Table
Attendence = CheckAttendance.Where(y => y.EmployeeId == x.EmployeeId).Count(),
InTime = CheckAttendance.Where(y => y.EmployeeId == x.EmployeeId).Select(y=>y.StartTime).ToList(),
OutTime = CheckAttendance.Where(y => y.EmployeeId == x.EmployeeId).Select(y=>y.EndTime),
C# api code
var TentId = objdb.Adminsitrators.Where(x => x.AdminId == AdminId).Select(x => x.TenantID).SingleOrDefault();
var emp = objdb.Employees.Where(x=>x.TenantID== TentId).ToList();
if (emp.Count > 0)
{
var CheckAttendance = objdb.EmpAttendances.Where(x => x.Status == "Present" & x.TenantID==TentId & x.StartTime.Year == StartTime.Year & x.StartTime.Month == StartTime.Month & x.StartTime.Day == StartTime.Day).ToList();
var list = emp.Select(x => new
{
EmpID = x.EmployeeId,
EmpName = x.Name,
EmpImage = "Areas/Admin/Image/" + x.Image,
Configured = fileResult(x.EmployeeId),
Attendence = CheckAttendance.Where(y => y.EmployeeId == x.EmployeeId).Count(),
InTime = CheckAttendance.Where(y => y.EmployeeId == x.EmployeeId).Select(y=>y.StartTime).ToList(),
OutTime = CheckAttendance.Where(y => y.EmployeeId == x.EmployeeId).Select(y=>y.EndTime),
}).ToList();
Value["result"] = "TRUE";
Value["Data"] = list;
}
JSON result
"result": "TRUE",
"Data": [
{
"EmpID": 14,
"EmpName": "Arun Kumar",
"EmpImage": "Areas/Admin/Image/EmployeeImg_55991775.JPG",
"Configured": 0,
"Attendence": 1, //Count Data
"InTime": [
"2019-05-21T16:13:18.873" //Tolist
],
"OutTime": [
"2019-05-21T16:12:51.967" //Select
]
},
Because you could have multiple InTime or OutTime values, so they are serialized as a JSON array, but when you .Count() a collection you turn it into a scalar value. Use .Max(), .First() or .OrderBy(...).Take(1), if you want to select a single value from a collection. Or .Single() if you know the collection always contains a single item.
Based on the relationshipt, Select and ToList may cause multiple results.
if you want the Max time or the last inserted value from Intime and OutTime you should query it. Also, you can use .FirstOrDefault() instead.

ElasticSearch & Nest - Wrong convertion

I have this pure call to Elastic that works. It returns 29 docs:
GET /idxsearch-test/movies/_search
{
"size": 20,
"query": {
"bool": {
"must": {
"bool" : {
"should": [
{"term": {"tag.name": "Paris"}},
{"multi_match" : {
"operator": "and",
"query" : "Paris",
"fields": ["movie_title.default^10",
"movie_title.snowball^2",
"movie_title.shingles^2",
"movie_title.ngrams"]}}
]
}
},
"filter": {
"term": { "is_adult": false }
}
}
},
"_source": ["id_content", "movie_title", "vote_average", "tag.name", "is_adult"]
}
I need to use Nest, so I converted to this. It returns 0:
var vod = client.Search<dynamic>(s => s
.Size(10)
.From(1)
.Index(defaultIndex)
.Type("movies")
.Query(qry1 => qry1
.FunctionScore(fs =>
fs.Query(qry2 =>
qry2.Bool(bool1 =>
bool1.Must(must1 =>
must1.Bool(bool2 =>
bool2.Should(should1 =>
{
QueryContainer qc = null;
qc &= should1.Term(tt => tt.Field("tag.name").Value(keywords));
qc &= should1.MultiMatch(mm1 => mm1.Fields(ff => ff
.Field("movie_title.default^10")
.Field("movie_title.snowball^2")
.Field("movie_title.shingles^2")
.Field("movie_title.ngrams"))
.Operator(Operator.And)
.Query(keywords));
return qc;
})
)
)
.Filter(fil =>
{
QueryContainer query = null;
if (!includeAdult)
query &= fil.Terms(fil2 => fil2.Field("is_adult").Terms(false));
return query;
})
)
)
.BoostMode(FunctionBoostMode.Sum)
.Functions(ff => ff.FieldValueFactor(fv => fv.Field("vote_average")
.Factor(0.5)
.Modifier(FieldValueFactorModifier.Log1P)))
))
);
But the results are different... What am I missing?
Is there a way to make the same call in a cleaner and correct way?
cheers
The first query can be written as
//Fluent
client.Search<dynamic>(
s => s.
Index("idxsearch-test").
Type("movies").
Take(20).
Query(q => q.Bool(
b => b.Must(m => m.Term(t => t.Field("tag.name").Value("Paris")) ||
m.MultiMatch(mm => mm.Fields(f => f.
Field("movie_title.default", 10).
Field("movie_title.snowball", 2).
Field("movie_title.shingles", 2).
Field("movie_title.ngrams")))).
Filter(f => includeAdult ? f.Term(t => t.Field("is_adult").Value("")) : null))).
Source(sc => sc.Includes(i => i.Field("id_content").Field("movie_title").Field("vote_average").Field("tag.name").Field("is_adult"))));
//Object
client.Search<dynamic>(new SearchRequest<dynamic>("idxsearch-test", "movies")
{
Size = 20,
Query = new BoolQuery
{
Must = new QueryContainer[]
{
new BoolQuery
{
Should = new QueryContainer[]
{
new TermQuery() { Field = "tag.name", Value = "Paris" },
new MultiMatchQuery
{
Fields = new [] { "movie_title.default^10", "movie_title.snowball^2", "movie_title.shingles^2", "movie_title.ngrams" }
}
}
}
},
Filter = includeAdult ? new QueryContainer[]
{
new TermQuery { Field = "is_adult", Value = false }
} : null
},
Source = new Union<bool, ISourceFilter>(new SourceFilter { Includes = new[] { "id_content", "movie_title", "vote_average", "tag.name", "is_adult" } })
});

GroupBy Date in LINQ C#

I am trying to GROUPBY Date in a LINQ Query and display the output as shown below
startdates: [
startdate: “4/1/2014”,
users: [
{userId, …},
{userId, …}
],
startdate: “4/2/2014”, users: [
{userId, …}
],
…
]
The code is shown below
db.Users
.Where(x => (x.startDate >= startDate) && (x.startDate <= endDate))
.GroupBy(x => new { x.startDate.Day, x.startDate.Month, x.startDate.Year })
.ToList()
.Select(y => new
{
startdates = y.Select(k =>
new {startdate = (k.startDate.Month.ToString() + "/" + k.startDate.Day.ToString() + "/" + k.startDate.Year.ToString()),
users = y.Select(z =>
new {userId = z.userId,
userName = z.userName})})});
Even though the Users are Grouped by StartDate, the output contains the startDate multiple times the same number of times as the number of Users.The output is shown below. I tried putting .Distinct() but it still repeats the startdate. Can someone please help?
[{"startdates":
[{"startdate":"04/01/2014",
"users":[
{"userId":1},"userName":"John"}
{"userId":2},"userName":"Mike"}],
[{"startdate":"04/01/2014",
"users":[
{"userId":1},"userName":"John"}
{"userId":2},"userName":"Mike"}],
[{"startdate":"04/02/2014",
"users":[
{"userId":3},"userName":"AL"}
{"userId":4},"userName":"Test"}],
[{"startdate":"04/02/2014",
"users":[
{"userId":3},"userName":"AL"}
{"userId":4},"userName":"Test"}]
The problem is your selection part, here:
.Select(y => new
{
startdates = y.Select(k =>
new {startdate = (k.startDate.Month.ToString() + "/" + k.startDate.Day.ToString() + "/" + k.startDate.Year.ToString()),
users = y.Select(z =>
new {userId = z.userId,
userName = z.userName})})});
You've got far too much nesting there. You're creating a startdate part for each element within the group.
It's unclear why you're using grouping by three separate parts at all, but I suspect this will do what you want:
db.Users
.Where(x => (x.startDate >= startDate) && (x.startDate <= endDate))
.GroupBy(x => x.startDate.Date) // Or just x.startDate
.AsEnumerable() // Do the rest of the query locally
.Select(group => new
{
startdate = group.Key.ToString("MM/dd/yyyy"),
users = group.Select(z => new { z.userId, z.userName })
});
If you need to wrap that in a startdates field, you can then use:
var result = new { startdates = query.ToArray() };

Categories

Resources