Expressions in firebase firestore security rule - firebase

The usage and limit (quotas) section of firebase clearly says that the firebase firestore security rule will allow only an expression with a maximum length of 1000 per request.But it does n't mentioning anything about the expressions.Can somebody explain about
1)What is an expression ?
2)How expression are evaluated ?
3)What are the possible way to reduce the length of evaluating expression ?

Good question on an undocumented subject. My understanding is the following:
1) Anything that is evaluated
2) Example:
match /somepath {
allow update: if request.resource.data.counter == resource.data.counter + 1
}
Here you have 10 expressions
request.resource.data.counter => 4
resource.data.counter => 3
1 => 1
== and + => 1 each = 2
3) Calculate only once...
Example:
match /somepath {
allow update: if request.resource.data.notchange1 == resource.data.notchange1 => 8 expressions
&& request.resource.data.notchange2 == resource.data.notchange2 => 8
&& request.resource.data.test1 > 0 => 6
&& request.resource.data.timestamp == request.time => 7
&& request.resource.data.counter == resource.data.counter + 1; => 10
}
=> 39 expressions in total
Better version:
match /somepath {
allow update: if checkupdate(); => 1
function checkupdate() {
let mapafter = request.resource.data; => 3
let map = request.resource; => 2
return mapafter.notchange1 == map.notchange1 => 5
&& mapafter.notchange2 == map.notchange2 => 5
&& mapafter.test1 > 0 => 4
&& mapafter.timestamp == request.time => 5
&& mapafter.counter == map.counter + 1; => 7
}
=> 32 expressions in total

Related

How do i count a column of bools grouped by date in LINQ?

I have a table that holds 15 session bookings by dates. Each row is a persons db entry for the sessions they attend.
For each date I need to count the bools for each session S1, S2 etc
How many are in S1 for 1/1/2019?.
Here is the table in asp.net core
![Pic of the table][https://imgur.com/a/SguJmLI]
It looks like this
Session S1 S2 S3 S4 S5 S6 S7
1/1/2019 1 0 1 1 1 0 1
1/1/2019 0 1 1 1 1 1 1
2/1/2019 0 0 1 1 1 1 1
2/1/2019 0 1 1 1 1 1 1
There are multiple session dates, and I need to get a summary count of the bools for each date.
1/1/2019 1 1 2 2 2 1 2
2/1/2019 0 1 2 2 2 2 2
Sadly I havn't got a single thing to generate
But this is how I am generating the grid
return View(await _context.SeatBooking
.OrderByDescending(s => s.SeatDate)
.ToListAsync());
Thanks guys,
Just a quick update this seems to work for me, but its clunky
ViewData["CountSessions"] = _context.SeatBooking
// .Where(s => s.StudentEmail == _userManager.GetUserId(User))
.GroupBy(d => d.SeatDate)
.Select(s => new
{
SumS1 = s.Count(c => c.S1 == true),
SumS2 = s.Count(c => c.S2 == true),
SumS3 = s.Count(c => c.S3 == true),
SumS4 = s.Count(c => c.S4 == true),
SumS5 = s.Count(c => c.S5 == true),
SumS6 = s.Count(c => c.S6 == true),
SumS7 = s.Count(c => c.S7 == true),
SumS8 = s.Count(c => c.S8 == true),
SumS9 = s.Count(c => c.S9 == true),
SumS10 = s.Count(c => c.S10 == true)
}).ToListAsync();
Since the Types of columns are bool, the first to do is to convert the bool to int .
Func<bool, int> convertBoolToInt = flag => flag ? 1 : 0;
var query = _context.SeatBooking
.Select(s => new SeatBookingDto
{
SeatDate = s.SeatDate,
S1 = convertBoolToInt(s.S1),
S2 = convertBoolToInt(s.S2),
S3 = convertBoolToInt(s.S3),
S4 = convertBoolToInt(s.S4),
S5 = convertBoolToInt(s.S5),
S6 = convertBoolToInt(s.S6),
S7 = convertBoolToInt(s.S7),
});
And now we can group and calculate the sum of each column for each group:
query.GroupBy(m => m.SeatDate, m => m, (k, g) => new
{
Date = k,
S1= g.Sum(m=>m.S1),
S2= g.Sum(m=>m.S2),
S3= g.Sum(m=>m.S3),
S4= g.Sum(m=>m.S4),
S5= g.Sum(m=>m.S5),
S6= g.Sum(m=>m.S6),
S7= g.Sum(m=>m.S7),
})
If you're using the EFCore , the corresponding query and result are :
App> SELECT [s].[SeatDate], [s].[S1], [s].[S2], [s].[S3], [s].[S4], [s].[S5], [s].[S6], [s].[S7]
App> FROM [SeatBooking] AS [s]
App> ORDER BY [s].[SeatDate]
App> 1/1/2019 12:00:00 AM : 1,1,2,2,2,1,2
App> 2/1/2019 12:00:00 AM : 0,1,2,2,2,2,2
Note the LINQ expression g.sum() here are all evaluated locally which means not evaluated by database . It seems that the EFcore has not evolved to be able to translate the Aggregate expression (such as Sum) to SQL query that can be executed on server .
If you want to query objects in memory only , there's another way to do that (not supported by EFCore yet) :
query.GroupBy(m=>m.SeatDate,m=>m,(k,g)=>new {
Date = k,
Count = g.Aggregate((c,n)=>new SeatBookingDto{
SeatDate=c.SeatDate,
S1=c.S1+n.S1,
S2=c.S2+n.S2,
S3=c.S3+n.S3,
S4=c.S4+n.S4,
S5=c.S5+n.S5,
S6=c.S6+n.S6,
S7=c.S7+n.S7,
})
})
I think you can try this:
_context.SeatBooking.Select(i => i.Session).Distinct().Select(i =>
new
{
Session = i,
S1 = _context.SeatBooking.Count(j => j.Session == i && j.S1 == 1),
S2 = _context.SeatBooking.Count(j => j.Session == i && j.S2 == 1),
}
).OrderByDescending(s => s.Session).ToList();

Linq summing by date in Asp.NET MVC

SiteCode | date |softwarename | Success | Error
ASZ 2017-08-5 a 1 1
ASZ 2017-08-5 b 2 2
ASZ 2017-08-5 a 3 3
ASZ 2017-08-6 a 6 6
NBL 2017-08-5 a 5 5
var CurrentCustomer = Database.Session.Query<Customer>()
.FirstOrDefault(x => x.deleted_at == null
&& x.Customer_Username == User.Identity.Name);
if(CurrentCustomer != null)
{
var CurrentDepValues = Database.Session.Query<deployments>()
.Where(x => x.SiteCode == CurrentCustomer.SiteCode
&& x.softwarename == current_type)
.OrderBy(x => x.date)
.ToList();
}
I have a db like that. I want to get an output like below. The same date values should be sum.
SiteCode | date |softwarename | Success | Error
ASZ 2017-08-5 a 4 4
ASZ 2017-08-6 a 6 6
Using a GroupBy:
if(CurrentCustomer != null) {
var CurrentDepValues = Database.Session.Query<deployments>()
.Where(x => x.SiteCode == CurrentCustomer.SiteCode
&& x.softwarename == current_type)
.GroupBy (x => new {x.SiteCode, x.date, x.softwarename})
.Select (g => new {
SiteCode = g.Key.SiteCode,
Date = g.Key.date,
SoftwareName = g.Key.softwarename,
Success = g.Sum(x => x.Success),
Error = g.Sum(x => x.Error)
})
.OrderBy(x => x.Date)
.ToList();
}
EDIT
The above will create an anonymous type.
If you would like to get List<Models.deployments>, you should do so in the select lambda:
.Select (g => new Models.deployments {
SiteCode = g.Key.SiteCode,
Date = g.Key.date,
SoftwareName = g.Key.softwarename,
Success = g.Sum(x => x.Success),
Error = g.Sum(x => x.Error)
})

Nested If Statement in Linq to SQL Query

In SQL I would normally type this out, hard to read - yes, but it does work
(IIF(Table1.Field1 = 1,
-- Field1 is True
IIF(Table2.Field2= 1, (SUM(Table1.Field3+Table1.Field4)),(SUM(Table1.Field3+Table1.Field4)*-1))
, -- Field1 is False
IIF(Table2.Field2= 1, (SUM((Table1.Field3+Table1.Field4)*-1)), (SUM(Table1.Field3+Table1.Field4))))) AS Result
How would I translate this to a Linq query, I know I can do ternary, but is it possible to nest ternary?
Also my goals are to do this in one database call.
You could write this using the ternary operator (?:) like this:
from t in db.Table1
group t by new { t.Field1, t.Field2 } into g
select
g.Key.Field1 == 1
? g.Key.Field2 == 1
? g.Sum(t => t.Field3 + t.Field4)
: -g.Sum(t => t.Field3 + t.Field4)
: g.Key.Field2 == 1
? -g.Sum(t => t.Field3 + t.Field4)
: g.Sum(t => t.Field3 + t.Field4)
But we can simplify this a bit to:
from t in db.Table1
group t by new { t.Field1, t.Field2 } into g
let s1 = g.Key.Field1 == 1 ? 1 : -1
let s2 = g.Key.Field2 == 1 ? 1 : -1
select s1 * s2 * g.Sum(t => t.Field3 + t.Field4)

Entity framework equivalent for NOT IN

I have a query like this
SELECT id
FROM params
WHERE valid=1
AND id NOT IN (SELECT pid
FROM clientparams
WHERE update = 0 AND client=15)
LIMIT 25
I am trying to convert it to entity framework equivalent:
IQueryable<Params> parame = db.Params.Where(p => p.valid.Equals(1)).Except(....);
But I am stuck at the point where I need to make an equivalent for the subquery
Any ideas how to solve it?
Try this
IQueryable<Params> parame = db.Params.Where(p => p.valid.Equals(1) &&
!db.clientParams.Any(e => e.pid == p.id && e.update == 0 && e.client == 15))
.OrderBy(e => e.id) //Order by any field.
.Take(25);

Linq divided by zero error?

How can check following code to catch divided by zero error?
active = (g.Sum(x => x.Kullanim_Reaktif) / g.Sum(x => x.kullanim_T0)) * 100
I want something like this:
if(g.Sum(x => x.kullanim_T0) == 0)
{
return 1;
}
else
{
return g.Sum(x => x.kullanim_T0);
}
Can I write if-else in above linq code line (g.Sum(x => x.kullanim_T0))? And how?
Thanks.
active = (g.Sum(x => x.kullanim_T0) == 0 ? 1 : g.Sum(x => x.Kullanim_Reaktif) / g.Sum(x => x.kullanim_T0)) * 100
but more efficient to do:
var kSum = g.Sum(x => x.kullanim_T0);
active = (kSum == 0 ? 1 : g.Sum(x => x.Kullanim_Reaktif) / kSum ) * 100

Resources