Raven Db Querying - ravendb

I am using Map Reduce index for query. And I want to select filter by licenceId/licenceIds which may be one or many separated by comma entered in text box
e.g.
L1 (select having LicenseId only L1)
L1,L2 (select having LicenseId only L1 OR L2)
L2,L3,L5 (select having LicenseId only L3 OR L3 OR L5)
Here is result document:
public class GrossSalesByRevenueClass
{
public string LicenseId { get; set; }
public string RevClass { get; set; }
public decimal GrossSales { get; set; }
public decimal NetSales { get; set; }
public int Quantity { get; set; }
public bool NonSales { get; set; }
public DateTime Day { get; set; }
public string DayName { get; set; }
public int Month { get; set; }
public int Quarter { get; set; }
public int Year { get; set; }
}
Index is:
public class IdxGrossSalesByRevenueClassByDay : AbstractIndexCreationTask<Ticket, GrossSalesByRevenueClass>
{
public IdxGrossSalesByRevenueClassByDay()
{
Map = docs => from doc in docs
from c in doc.Coversfrom t in c.TicketItems
select new
{
LicenseId = doc.LicenseId,
RevClass = t.RevenueClass,
GrossSales = t.TicketItemGross,
NetSales = t.NetPrice,
Quantity = t.Quantity,
NonSales = t.IsNonSales,
Day = doc.TicketDate.Date,
DayName = doc.TicketDate.ToString("ddd")
};
Reduce = result => from r in result
group r by new { r.NonSales, r.RevClass, r.Day, r.LicenseId } into g
select new
{
LicenseId = g.Key.LicenseId,
RevClass = g.Key.RevClass,
GrossSales = g.Sum(x => x.GrossSales),
NetSales = g.Sum(x => x.NetSales),
Quantity = g.Sum(x => x.Quantity),
NonSales = g.Key.NonSales,
Day = g.Key.Day,
DayName = g.Select(x => x.DayName).FirstOrDefault(),
};
}
}
And I am querying like following:
GrossSalesByRevenueClassCollection = session.Query<GrossSalesByRevenueClass, IdxGrossSalesByRevenueClassByDay>()
.TransformWith<GrossSalesByRevenueClassTransformer, GrossSalesByRevenueClass>()
.Where(x => x.Day >= d1 && x.Day <= d2 && (?????))
In place of (?????) there should be License id list (L1 OR L2)
I tried Contains() in where but not working for me please tell me how do I query an index
for such a requirement.

something like this
var licenses = userLicenses.Split(",");
GrossSalesByRevenueClassCollection = session.Query<GrossSalesByRevenueClass, IdxGrossSalesByRevenueClassByDay>()
.Where(x => x.Day >= d1 && x.Day <= d2 && x.LicenseId.In(licenses))

Related

How to rewrite Entity Framework query to SQL Server query

I have a table called passenger policy that looks like this:
public Guid HotelId { get; set; }
public int FromAge { get; set; }
public int ToAge { get; set; }
public PassengerType PassengerType { get; set; }
and it has 3 rows for each HotelId key.
I have another table called search that looks like this
public class Search : BaseEntity
{
public DateTime Date { get; set; }
public Guid CountryId { get; set; }
public Guid ProvinceId { get; set; }
public Guid CityId { get; set; }
public Guid HotelId { get; set; }
public Guid VendorHotelRoomId { get; set; }
public int StandardCapacity { get; set; }
public int ExtraCapacity { get; set; }
public int MaxInfantAge { get; set; }
public int MaxChild1Age { get; set; }
public int MaxChild2Age { get; set; }
public double BasePrice { get; set; }
public double ExtraAdultPrice { get; set; }
public double ExtraInfantPrice { get; set; }
public double ExtraChild1Price { get; set; }
public double ExtraChild2Price { get; set; }
}
I want to write a query in T-SQL (SQL Server) to get hotels based on date field, standard capacity and extra capacity.
The extra capacity has 3 possible values:
infant
child 1
child 2
(fetched from passenger type table)
I write it like this in EF Core
var searchOnAllVendors hotelContext.Search
.Where(c => c.Date >= fromDate
&& c.Date <= toDate
&& c.CityId == cityId
&& c.ExtraCapacity >= adultCount)
.AsEnumerable();
foreach (var item in searchOnAllVendors)
{
foreach (var ag in request.Passengers.ChildrensAges)
{
if (ag <= item.MaxInfantAge && ag < item.MaxChild1Age && ag < item.MaxChild2Age)
infant++;
if (ag > item.MaxInfantAge && ag <= item.MaxChild1Age)
child1Count++;
if (ag > item.MaxChild1Age && ag <= item.MaxChild2Age)
child2Count++;
if (ag > item.MaxChild1Age && ag <= item.MaxChild2Age)
extraAdult++;
}
if (item.MaxInfantAge >= infant && item.MaxChild1Age >= child1Count && item.MaxChild2Age >= child2Count)
{
var adulPrice = extraAdult * item.ExtraAdultPrice;
var infantPrice = infant * item.ExtraInfantPrice;
var child1Price = child1Count * item.ExtraChild1Price;
var child2Price = child1Count * item.ExtraChild2Price;
var finalPrice = adulPrice + infantPrice + child1Price + child2Price + item.BasePrice;
searches.Add(new Search_Response
{
CityId = item.CityId,
CountryId = item.CountryId,
HotelId = item.HotelId,
ProvinceId = item.ProvinceId,
VendorHotelRoomId = item.VendorHotelRoomId,
Price = finalPrice
});
}
}
after couple days and try a few things i find a way to have best performance in T-SQL
...
1. Get count of extra passernger types in scalar-valued functions like this :
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[GetChildRule](#ages as nvarchar(max),#min as int,#max as int)
RETURNS int
AS
BEGIN
declare #count int
select #count=count(*) from STRING_SPLIT(#ages,',')
where value > #min and value <= #max
RETURN #count
END
...
and use it in stored procedure like a field as below :
select * , GetChildRule('1,2,3',mymin,mymax) from Search where date between date1 and date2
and call it in EF CORE:
Context.Set<YourModelWithAllOfFiledYouReturnInSP>()
.FromSqlRaw($"EXEC [dbo].[StaySearch] #extraAges = N'{ages}',
#checkInDate = N'{fromDate}', #checkOutDate = N'{toDate}',
#destinationId = '{destinationId}',
#countrySearch = '{countrysearch}',#adultCount={adultCount}");

how to use in clause in Linq Query and pass it dynamically from code

I am converting my project to EF Core in my old project I have a query running.
IDictionary<int, IGrouping<int, UserPurchaseItemAddonWithAmount>> addons =
context.Fetch<UserPurchaseItemAddonWithAmount>($"Select UPIA.*, EA.Amount From UserPurchaseItemAddons UPIA Inner Join ExtraAddons EA on UPIA.AddonID = EA.AddonID Where UPIA.UserPurchaseItemID in ({string.Join(',', userPurchaseItems.Select(S => S.UserPurchaseItemID))})")
.GroupBy(G => G.UserPurchaseItemID).ToDictionary(D => D.Key);
I need to convert this query in to Linq query what I am doing is below
IDictionary<int, IGrouping<int, UserPurchaseItemAddonWithAmount>> addons =
(from f in context.UserPurchaseItemAddons
join s in context.ExtraAddons
on f.AddonId equals s.AddonId
select new
{
Amount = s.Amount,
UserPurchaseItemAddonID = f.UserPurchaseItemAddonId,
UserPurchaseItemID = f.UserPurchaseItemId,
BranchItemVariantID = f.BranchItemVariantId,
AddonID = f.AddonId,
UserID = f.UserId,
IsDeleted = f.IsDeleted,
ModifiedOn = f.ModifiedOn,
ModifiedBy = f.ModifiedBy,
Reason = f.Reason,
}).GroupBy(G => G.UserPurchaseItemID).ToDictionary(D => D.Key);
This query is causing a compiler error related to casting to IGrouping<int, UserPurchaseItemAddonWithAmount> to an anonymous type. The other thing is that how can I apply in clause in where condition in above query, just like the first query .
class
public class UserPurchaseItemAddonWithAmount
{
public decimal Amount { get; set; }
public int UserPurchaseItemAddonID { get; set; }
public int UserPurchaseItemID { get; set; }
public int BranchItemVariantID { get; set; }
public int AddonID { get; set; }
public int UserID { get; set; }
public bool IsDeleted { get; set; }
public DateTime? ModifiedOn { get; set; }
public int? ModifiedBy { get; set; }
public string? Reason { get; set; }
}
Try the following query. Main mistake that you have returned anonymous class.
var purchaseItemIds = userPurchaseItems.Select(S => S.UserPurchaseItemID);
IDictionary<int, IGrouping<int, UserPurchaseItemAddonWithAmount>> addons =
(from f in context.UserPurchaseItemAddons
join s in context.ExtraAddons on f.AddonId equals s.AddonId
where purchaseItemIds.Contains(f.UserPurchaseItemID)
select new UserPurchaseItemAddonWithAmount
{
Amount = s.Amount,
UserPurchaseItemAddonID = f.UserPurchaseItemAddonId,
UserPurchaseItemID = f.UserPurchaseItemId,
BranchItemVariantID = f.BranchItemVariantId,
AddonID = f.AddonId,
UserID = f.UserId,
IsDeleted = f.IsDeleted,
ModifiedOn = f.ModifiedOn,
ModifiedBy = f.ModifiedBy,
Reason = f.Reason,
})
.AsEnumerable()
.GroupBy(G => G.UserPurchaseItemID)
.ToDictionary(D => D.Key);

How to convert my SQL query to a LINQ statement

I am not familiar with linq complex queries, how can I write the following?
Three tables: Library,Batch,Plan
Library: BatchId ProcessingQuantity
Batch: BatchId
Plan: PlanNo Name Quantity ExecState Date
SELECT b.ProductionPlanBatchId,
a.ProductionPlanNo,
a.ProductConfigName,
sum(c.ProcessingQuantity) AS 'ProcessingQuantity',
sum(a.Quantity) AS 'Quantity',
a.ExecState,
round(CONVERT(float,sum(c.ProcessingQuantity))/CONVERT(float,sum(a.Quantity)), 2) AS 'Percent',
a.ProcessingCompletionDate
FROM ProductionPlan a,
ProductionPlan_Batch b,
ProductionLibrary c
WHERE a.ProductionPlanId = b.ProductionPlanId
AND b.ProductionPlanBatchId = c.ProductionPlanBatchId
AND a.ExecState <> 'Deleted'
GROUP BY b.ProductionPlanBatchId,
a.ProductionPlanNo,
a.ProductConfigName,
a.ProcessingCompletionDate,
a.ExecState
HAVING round(Convert(float,sum(c.ProcessingQuantity))/Convert(float,sum(a.Quantity)), 2) < 1
ORDER BY b.ProductionPlanBatchId DESC
According to your description, I suggest you could try to use below linq.
Class:
[Table("ProductionLibrary")]
public partial class ProductionLibrary
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ProductionPlanBatchId { get; set; }
public int? ProcessingQuantity { get; set; }
}
[Table("ProductionPlan")]
public partial class ProductionPlan
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ProductionPlanNo { get; set; }
[StringLength(10)]
public string ProductConfigName { get; set; }
public int? Quantity { get; set; }
[StringLength(10)]
public string ExecState { get; set; }
[StringLength(10)]
public string ProcessingCompletionDate { get; set; }
public int? ProductionPlanId { get; set; }
}
public partial class ProductionPlan_Batch
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ProductionPlanBatchId { get; set; }
public int? ProductionPlanId { get; set; }
}
Linq:
var re = from a in dbcontext.ProductionPlans
from b in dbcontext.ProductionPlan_Batch
from c in dbcontext.ProductionLibraries
where a.ProductionPlanId == b.ProductionPlanId
&& b.ProductionPlanBatchId == c.ProductionPlanBatchId
&& a.ExecState != "Deleted"
select new
{
a.ExecState,
a.ProcessingCompletionDate,
a.ProductConfigName,
a.ProductionPlanId,
a.ProductionPlanNo,
a.Quantity,
b.ProductionPlanBatchId,
bProductionPlanId = b.ProductionPlanId,
c.ProcessingQuantity,
cProductionPlanId = c.ProductionPlanBatchId
}
into p
group p by new {
p.ProductionPlanId,
p.ProductionPlanNo ,
p.ProductConfigName,
p.ProcessingCompletionDate,
p.ExecState,
p.ProductionPlanBatchId
} into grpre
where Math.Round(((decimal)grpre.Sum(x => x.ProcessingQuantity))/((decimal)grpre.Sum(x => x.Quantity)), 2) <1
orderby grpre.Key.ProductionPlanBatchId descending
select new {
grpre.Key.ProductionPlanBatchId,
grpre.Key.ProductionPlanNo,
grpre.Key.ProductConfigName,
ProcessingQuantity = grpre.Sum(x =>x.ProcessingQuantity) ,
Quantity = grpre.Sum(x => x.Quantity),
grpre.Key.ExecState,
Percent = Math.Round(((decimal)grpre.Sum(x => x.ProcessingQuantity)) / ((decimal)grpre.Sum(x => x.Quantity)), 2),
grpre.Key.ProcessingCompletionDate
};

Need Help using Groupby and Join together in Query Statement for MVC

I have two models: Departments and Invoice.
public partial class Invoice
{
public int Id { get; set; }
public int VendorId { get; set; }
public int DepartmentID { get; set; }
public string ItemName { get; set; }
public decimal Price { get; set; }
public DateTime Date { get; set; }
}
public partial class Department
{
public int Id { get; set; }
public string Departments { get; set; }
public virtual ICollection<Invoice> Invoices { get; set; }
}
I am trying to group by Departments and list total price per Department. I may be almost there with but leaning towards totally lost so any help would be appreciated.
For example:
Foo - $135
Bar - $450
What I have now but I am lost with the select portion of statement:
var deptGroup = content.Departments
.Join(content.Invoices, d => d.Id, i => i.DepartmentID, (d, i) => new { Department = d, Invoice = i })
.GroupBy(d => d.Department.Departments)
.OrderBy(d => d.Key);
You're almost there, you just need to select the sum of the invoice prices for each group:
var deptGroup = content.Departments
.Join(content.Invoices, d => d.Id, i => i.DepartmentID, (d, i) => new { Department = d, Invoice = i })
.GroupBy(d => d.Department.Departments)
.OrderBy(d => d.Key)
.Select(d => new
{
DepartmentName = d.Key,
TotalPrice = d.Sum(i => i.Price)
};
It's worth noting that you shouldn't need to use your own joins and groupings for this, though, since each Department already has a collection of invoices on it:
var deptGroup = content.Departments
.Select(d => new
{
DepartmentName = d.Departments,
TotalPrice = d.Invoices.Sum(i => i.Price)
})
.OrderBy(d => d.DepartmentName);

Why do I get this error in a RavenDB index query: The field 'CustomerId' is not indexed

This is my index code:
public class InvoiceSummaryView
{
public DateTime DueDate { get; set; }
public string CompanyAddress { get; set; }
public string DebtorName { get; set; }
public float Amount { get; set; }
public bool IsPaid { get; set; }
public string CustomerId { get; set; }
}
public class InvoiceSummaryIndex : AbstractIndexCreationTask<CustomerInvoice>
{
public InvoiceSummaryIndex()
{
Map = invoices => from invoice in invoices
select new { DueDate = invoice.DueDate, DebtorId = invoice.DebtorId, Amount = invoice.Amount };
TransformResults = (database, results) =>
from invoice in results
let debtor = database.Load<Debtor>(invoice.DebtorId)
let company = database.Load<Company>(debtor.CompanyId)
select new {
DueDate = invoice.DueDate,
CompanyAddress = Company.Address.ToString(),
DebtorName = debtor.Contact.First + " " + debtor.Contact.Last,
Amount = invoice.Amount,
IsPaid = invoice.IsPaid,
CustomerId = Company.CustomerId
};
}
}
And this is my query:
var query = from viewItem in session.Query<InvoiceSummaryView>("InvoiceSummaryIndex")
where viewItem.CustomerId == id
orderby viewItem.DueDate
select viewItem;
the error is:
"Error": "System.ArgumentException: The field 'CustomerId' is not indexed,
cannot query on fields that are not indexed at ...
Look at your index:
select new { DueDate = invoice.DueDate, DebtorId = invoice.DebtorId, Amount = invoice.Amount };
The fields that you have indexed are DueDate, DebtorId and Amount, that is it.
If you'll it it like this:
select new { DueDate = invoice.DueDate, DebtorId = invoice.DebtorId, Amount = invoice.Amount, invoice.CustomerId };
It will work