RavenDB using filter with group by - linq

I have a Transaction entity.
I can make group by by (CustomerCode, CustomerName) then select CustomerCode and Total(Amount).
It is easy. But When I Want to filter AtCreated. I have An Error.
Unhandled exception. Raven.Client.Exceptions.InvalidQueryException: Raven.Client.Exceptions.InvalidQueryException: Field 'AtCreated' isn't neither an aggregation operation nor part of the group by key
Query: from Transactions group by CustomerCode, CustomerName where AtCreated >= $p0 select CustomerCode, count() as Total
Parameters: {"p0":"2019-01-01T00:00:00.0000000"}
public class Transactions
{
public string Id { get; set; }
public long TransId { get; set; }
public DateTime AtCreated { get; set; }
public string CustomerCode { get; set; }
public string CustomerName { get; set; }
public string City { get; set; }
public double Amount { get; set; }
public string GXF { get; set; }
}
var transactList = session.Query<Transactions>()
.Where(a=>a.AtCreated >= new DateTime(2019,01,01))
.GroupBy(a => new {a.CustomerCode, a.CustomerName})
.Select(a => new {a.Key.CustomerCode, Total = a.Count()})
.ToList();
How can I Grouping filtered data?
Thank You.

Create a Map-Reduce Index and then query on it.
https://ravendb.net/docs/article-page/4.2/csharp/indexes/map-reduce-indexes
For example, in this example, you can query on 'Category' field because it was indexed (meaning it was part of the Map-Reduce index definition)
See short demo examples in:
https://demo.ravendb.net/

Related

Fetching the highest value from CosmosDb table

With the SDK of Azure.Data.Tables I’m trying to write a query that groups the data and fetches the highest value from each group. Is there a way to achieve this?
Currently I’m fetching all the data and executing the following LINQ query:
public class SomeClass
{
public string CompanyName { get; set; }
public long SomeValue { get; set; }
public string ProperyAttribute1 { get; set; }
public string ProperyAttribute2 { get; set; }
public long ProperyAttribute3 { get; set; }
}
List<SomeClass> someList = FetchingDataFromCosmosDbTableStorage(); //fetching all the data
var result = someList.GroupBy(x => x.CompanyName)
.Select(y => y.OrderByDescending(i => i.SomeValue).First())
.ToList();
Instead of filtering all the data in my application I would prefer to write a query to get the same result from CosmosDb Table.

Filter list by grandchild using LINQ

I need to filter a list by the DamageCodeName field in the DamageCode class.
public partial class DamageCategory
{
public string DamageCategoryId { get; set; }
public string CategoryName { get; set; }
}
public partial class DamageGroup
{
public string DamageGroupId { get; set; }
public string DamageCategoryId { get; set; }
public string GroupName { get; set; }
}
public partial class DamageCode
{
public string DamageCodeId { get; set; }
public string DamageGroupId { get; set; }
public string DamageCodeName { get; set; }
}
I pull the records using EF CORE 5 into a list:
private List<DamageCategory> _DamageCodeList { get; set; } = new();
_DamageCodeList = _contextDB.DamageCategories
.Include(i => i.DamageGroups)
.ThenInclude(d => d.DamageCodes).AsSingleQuery().ToListAsync();
Now I need to filter this list by the DamageCode.DamageCodeName property.
private string _SearchText { get; set; } = "Bubble";
private List<DamageCategory> _CategoryList { get; set; } = new();
_CategoryList = _DamageCodeList.Where(g => g.DamageGroups.SelectMany(c => c.DamageCodes
.Where(w => w.DamageCodeName.ToLower().Contains(_SearchText.ToLower()))).Any()).ToList();
The code above only filters for the DamageCategory. It brings back all the records for the DamageGroup and all the records for the DamageCodes.
I need the linq query result to produce a list like the one below (Filtered by "Bubble") and bring back only the DamageCategory, DamageGroup, and DamageCodes filtered by DamageCode.DamageCodeName.Contains("Bubble"):
Here is the SQL that produces the result above that I need:
SELECT
CT.[DamageCategoryID],
CT.[CategoryName],
DG.[DamageGroupID],
DG.[DamageCategoryID],
DG.[GroupName],
DC.[DamageCodeID],
DC.[DamageGroupID],
DC.[DamageCodeName]
FROM
[dbo].[DamageCategory] AS CT
INNER JOIN [dbo].[DamageGroup] AS DG ON CT.[DamageCategoryID] = DG.[DamageCategoryID]
INNER JOIN [dbo].[DamageCode] AS DC ON DG.[DamageGroupID] = DC.[DamageGroupID]
WHERE
DC.[DamageCodeName] LIKE '%Bubble%'
This is where query syntax shines.
from dc in _contextDB.DamageCategories
from dg in dc.DamageGroups
from dc in dg.DamageCodes
where dc.DamageCodeName.Contains("Bubble")
select new
{
dc.DamageCategoryID,
dc.CategoryName,
dg.DamageGroupID,
dg.DamageCategoryID,
dg.GroupName,
dc.DamageCodeID,
dc.DamageGroupID,
dc.DamageCodeName
}
The query shape from ... from is the query syntax equivalent of SelectMany.
You use ToLower in your code. That may not be necessary. The query is translated into SQL and if the database field has a case-insensitive collation you don't need ToLower.

Linq SQL EF Core subselect always requests ALL columns for tables in subquery from database

I have an ASP.NET Core 3.1 with EF Core Web API running in front of a SQL Server. Front end is Angular.
There is a function where someone is able to select the campaigns that are running for multiple selected clients.
The models involved are:
public partial class Campaign
{
public int CampaignId { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int AdvertiserId { get; set; }
public int SalesHouseId { get; set; }
}
public partial class Customer
{
public int CustomerId { get; set; }
public string CompanyName { get; set; }
public string SearchCode { get; set; }
public string PhoneNumber1 { get; set; }
public string PhoneNumber2 { get; set; }
public string FaxNumber { get; set; }
public string Email { get; set; }
public string CompanyURL { get; set; }
public bool IsOnHold { get; set; }
public DateTime? OnHoldSince { get; set; }
public string OnHoldBy { get; set; }
public .... more fields { get; set; }
}
I use the following LinqSql to pull the campaigns for the selected clients (example):
List<int> selectedClients = new List<int>() { 10414, 19529, 14025 };
var cams = (from cam in _dbContext.Campaigns
join cl in (from cus in _dbContext.Customers.Where(cus =>
selectedClients.Contains(cus.CustomerId))
select new { cus.CustomerId, cus.CompanyName })
on cam.AdvertiserId equals cl.CustomerId
select new { cam.CampaignId, cam.Description, cam.StartDate, cl.CompanyName})
.AsNoTracking()
.ToList();
The result returned is good and all works fine.
BUT I checked the SQL that is send down to the server and noticed that for the sub query ALL columns are requested:
SELECT [c].[CampaignId], [c].[Description], [c].[StartDate], [t].[CompanyName]
FROM [Campaigns] AS [c]
INNER JOIN (
SELECT [c0].[CustomerId], [c0].[ACEndDate], [c0].[ACStartDate], [c0].[ActiveSince], [c0].[AgencyCommission], [c0].[Balance], [c0].[BalanceDate], [c0].[BankAccount], [c0].[CompanyName], [c0].[CompanyURL], [c0].[CreditLimit], [c0].[DebtorNumber], [c0].[Email], [c0].[EmailInvoice], [c0].[EmailOrderConfirmation], [c0].[FaxNumber], [c0].[FinanciallyResponsibleCustId], [c0].[InactiveSince], [c0].[InvDueDays], [c0].[InvFreqMargin], [c0].[InvoiceFrequency], [c0].[InvoiceInfo], [c0].[IsActive], [c0].[IsAdvertiser], [c0].[IsAdvertisingAgency], [c0].[IsAgency], [c0].[IsApprovedAgency], [c0].[IsDirectAdvertiser], [c0].[IsFinanciallyResponsible], [c0].[IsHolding], [c0].[IsOnHold], [c0].[IsOther], [c0].[IsProductionCompany], [c0].[IsTaxable], [c0].[OnHoldBy], [c0].[OnHoldReason], [c0].[OnHoldSince], [c0].[PaymentMethod], [c0].[PhoneNumber1], [c0].[PhoneNumber2], [c0].[PrintOrderConfirmation], [c0].[PrintZeroInvoices], [c0].[SearchCode], [c0].[SetInactiveBy], [c0].[VATId], [c0].[VATNumber]
FROM [Customers] AS [c0]
WHERE [c0].[CustomerId] IN (10414, 19529, 14025)
) AS [t] ON [c].[AdvertiserId] = [t].[CustomerId]
ALL columns from the table in the subquery are send back to the API. I only need the [customerId] and [companyName] fields.
I tried to use a DTO instead of the anonymous select in the subquery but that does not help either.
If the subselect consists of more tables, all columns of all tables in that sub select will be requested from the database.
Does anyone have an idea how to limit the columns from the sub-select here?

Linq Left Join with Lambda Count

I have a Users and a Shipments table. The Shipments table has a property Received. I want to write code to get all Users where all their shipments have been received (received == true) with linq.
Users table
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool NeedsFilament { get; set; }
public ICollection<Shipment> Shipments { get; set; }
Shipments table
public Guid Id { get; set; }
public int Quantity { get; set; }
public DateTime DateShipped { get; set; }
public bool Recieved { get; set; }
public Guid UserId { get; set; }
public User User { get; set; }
What I've done so far in a SQL query that doesn't count the Received props in Shipments but just gets the distinct (it's wrong)
SELECT DISTINCT
[FirstName]
,[LastName]
,[Username]
,[Address]
,[LatestShippedDate]
,[PrinterActive]
,[ProductionDate]
,[ShippedQuantity]
,[Email]
,[PhoneNumber]
,[NeedsFilament]
,[FilamentTrackingNumber]
,[SentFilamentDate]
,[LatestShippedQuantity]
FROM
[dbo].[Users]
LEFT JOIN
Shipments ON Shipments.UserId = Users.Id
WHERE
Shipments.Recieved = 1
AND Users.NeedsFilament = 1
Hello #Pt4r the below Linq statement will do that you want, the below line parse the users_table and compare each element of two tables and keep those elements which statement return true
var newUserTbl = users_table.Where(user=>Shipments.UserId==user.id && Shipments.Recieved).ToList();

Linq Query Help on outter join against a list in and object

I have the following object Job and Job sor are populated by reading in data from an XML file and Sor is populated from a database.
class Job
{
public int JobID { get; set; }
public string DepartmentCode { get; set; }
public string ClientReference { get; set; }
public string JobDescription { get; set; }
public List<JobSor> JobSorList { get; set; }
}
class JobSor
{
public int JobID { get; set; }
public string SorUserCode { get; set; }
public string SorNotes1 { get; set; }
public string SorNotes2 { get; set; }
}
class Sor
{
[Key]
public string code { get; set; }
public string description { get; set; }
public string contract { get; set; }
}
I want to write a linq query that will show me all the JobSors that do not exist in the Sor object.
This is what I have so far but I can’t reference the SorUserCode property?
var db = new dbContext();
var sor = db.Sors.Where(p => p.contract == "??");
var query =
from j in jobs
join p in sor on j.JobSorList.SorUserCode equals p.code into jp
from a in jp.DefaultIfEmpty()
select j;
How can I do this?
First get list of all JobSor from jobs list.
Then apply condition Where its SorUserCode value does not match with Any code value of the sor list.
Your query will be as below.
var query = jobs.SelectMany(x => x.JobSorList)
.Where(x => !sor.Any(y => y.code == x.SorUserCode));

Resources