Using lodash for grouping data - lodash

There is an array of JS objects. Object has the following attributes:
year
name
salary
The array is sorted by (year + name). It is given what there are only 2 different values in "name" attribute.
The goal is to generate another JS array, sorted by year, containing objects with 2 attributes only:
year
100 * (salary for name#1) / (salary for name#2)
If one of the salaries does not exists or 0 for given year then the object shell not be created for this year.
I tried to use _lodash (I am not sure this is the right tool for this):
var groupByYear =_.groupby(myArray, function(element){
return element.year;
};
return _.map(groupByYear, function(el){
if (el.size() == 2 and el[0].salary > 0 and el[1].salary > 0)
return { "year": el[0].year , "percent": 100 * el[0].salary / el[1].salary };
}
but I am not confident this is right approach; for example the intermediate array named groupByYear is created.

Try this maybe:
_.chain(arr)
.groupBy('year')
.map((salary, year) => [year, 100 * salary[0].salary / salary[1].salary])
.sortBy('0')
.value()

Related

How to modify value in column typeorm

I have 2 tables contractPoint and contractPointHistory
ContractPointHistory
ContractPoint
I would like to get contractPoint where point will be subtracted by pointChange. For example: ContractPoint -> id: 3, point: 5
ContractPointHistory has contractPointId: 3 and pointChange: -5. So after manipulating point in contractPoint should be 0
I wrote this code, but it works just for getRawMany(), not for getMany()
const contractPoints = await getRepository(ContractPoint).createQueryBuilder('contractPoint')
.addSelect('"contractPoint".point + COALESCE((SELECT SUM(cpHistory.point_change) FROM contract_point_history AS cpHistory WHERE cpHistory.contract_point_id = contractPoint.id), 0) AS points')
.andWhere('EXTRACT(YEAR FROM contractPoint.validFrom) = :year', { year })
.andWhere('contractPoint.contractId = :contractId', { contractId })
.orderBy('contractPoint.grantedAt', OrderByDirection.Desc)
.getMany();
The method getMany can be used to select all attributes of an entity. However, if one wants to select some specific attributes of an entity then one needs to use getRawMany.
As per the documentation -
There are two types of results you can get using select query builder:
entities or raw results. Most of the time, you need to select real
entities from your database, for example, users. For this purpose, you
use getOne and getMany. But sometimes you need to select some specific
data, let's say the sum of all user photos. This data is not an
entity, it's called raw data. To get raw data, you use getRawOne and
getRawMany
From this, we can conclude that the query which you want to generate can not be made using getMany method.

Retrieving JSON elements that don't share a key

I have a JSON that looks like this:
"names": {
"jack": {
"probability": 0
},
"bob": {
"probability": 0.5
},
"ana": {
"probability": 0.2
}
"bill": {
}
And I want to query it to get a table of names and probabilities, and in case there is no value of probability, get 0.
So the output should look like this:
name probability
jack 0
bob 0.5
ana 0.2
bill 0
Couldn't find a way to query the json in a proper way to get these results. I am using Postgresql.
You are looking for the jsonb_each() function:
select n.name, coalesce(val ->> 'probability', '0')::numeric
from the_table t
cross join jsonb_each( t.col -> 'names') as n(name, val)
If you column isn't jsonb (which it should), but json, you have to use json_each() instead.
Online example

Get multiple distinct values from query in Entity Framework

I'm running a query that will get results based on a location search and date. I have a geography column with location points (lat/long) that's indexed. When I search for an event on a date it searches for all events within a distance (radius) on that date.
The problem is that if there are, say 10 events, all at the same location on the same date, all 10 results will come back in the first page. I'd like to mix this up and only show 2-3 from each location to give the result set some variety, so the user doesn't just see all events from one location.
I know I can use distinct to only fetch one event from each location, but how would I use it to get me 2-3 distinct values?
Here is my query so far.
viewModel.Events = dbContext.YogaSpaceEvents
.Where(i => i.EventDateTime >= adjustedSearchDate &&
i.LocationPoints.Distance(location) <= radius)
.Distinct()
.OrderBy(i => i.EventDateTime)
.Select(i => new EventResult
{
//fill view model here
})
.ToPagedList(Page, 10);
I don't think there's a way to get EF to generate such a query, which for SQL Server would be something like this:
with q as
(
select *,
( row_number() over (partition by StateProvinceId order by CityID) -1 ) / 3 MyRanking
from Application.Cities
)
select CityId, CityName,StateProvinceID
from q
order by MyRanking, StateProvinceID, CityID
offset 10 rows
fetch next 20 rows only
Note that this example doesn't use distance. But the idea is identical: the first 3 cities in each state are returned first, then the next 3, etc.
Or you could fetch all the matching events and sort them in memory.
I think you should be able to do something like:
dbContext.YogaSpaceEvents
.Where(i => i.EventDateTime >= adjustedSearchDate &&
i.LocationPoints.Distance(location) <= radius)
.GroupBy(i => i.Geography)
.SelectMany(g => g.OrderBy(x => x.EventDateTime).Take(3))
.Select(i => new EventResult { //fill view model here })
.ToPagedList(Page, 10);

Using LINQ to pull collection until aggregate condition met

At a high level, I need a query that can pull a subset of records based on the sum of a column, just like Linq: How to query items from a collection until the sum reaches a certain value.
However, the key difference is that he's already got his records in an object, and I don't and can't. My table can have millions of records. If I build my query the way he did, I get this error:
"A lambda expression with a statement body
cannot be converted to an expression tree"
Which makes sense after researching it, LINQ can't turn the answer in the above referenced question into valid SQL.
I'm going to make a hypothetical table that represents my situation.
Order Id | Cookie Name | Qty
1 Sugar 5
2 Snickerdoodle 4
3 Chocolate chip 8
4 Snickerdoodle 10
5 Snickerdoodle 5
Given this sample, I need to write a query that grabs the first X orders of Snickerdoodle until the summed Qty exceedes an input from the parameter (i.e. If the user chooses 13, it would return records 2 & 4 ).
I'm using Nhibernate.Linq, because I'm more comfortable in LINQ. I'm completely open to ICreate if the need arises.
As a side note, I'm interested in this as a concept as well as a direct problem. Even though I need a Sum, there has to be a way to do something akin to a takewhile that executes until a condition is met.
pragmatic approach
int needed = ...;
int actual = 0;
int page = 0;
const int pagesize = 20; // set to some sensible value, eg. the pagesize of the grid shown to the user
var results = new List<CookieOrder>();
while (actual < needed)
{
var partialResults = session.Query<CookieOrder>()
.Where(c => c.Name == "Snickerdoodle")
.OrderBy(c => c.Id)
.Skip(page * pagesize)
.Take(pagesize)
.ToList();
for(int i = 0; i < partialResults.Length && actual < needed; i++)
{
results.Add(partialResults[i]);
actual = partialResults[i].Quantity;
}
page++;
}
return results;

Raven DB Count Queries

I have a need to get a Count of Documents in a particular collection :
There is an existing index Raven/DocumentCollections that stores the Count and Name of the collection paired with the actual documents belonging to the collection. I'd like to pick up the count from this index if possible.
Here is the Map-Reduce of the Raven/DocumentCollections index :
from doc in docs
let Name = doc["#metadata"]["Raven-Entity-Name"]
where Name != null
select new { Name , Count = 1}
from result in results
group result by result.Name into g
select new { Name = g.Key, Count = g.Sum(x=>x.Count) }
On a side note, var Count = DocumentSession.Query<Post>().Count(); always returns 0 as the result for me, even though clearly there are 500 odd documents in my DB atleast 50 of them have in their metadata "Raven-Entity-Name" as "Posts". I have absolutely no idea why this Count query keeps returning 0 as the answer - Raven logs show this when Count is done
Request # 106: GET - 0 ms - TestStore - 200 - /indexes/dynamic/Posts?query=&start=0&pageSize=1&aggregation=None
For anyone still looking for the answer (this question was posted in 2011), the appropriate way to do this now is:
var numPosts = session.Query<Post>().Count();
To get the results from the index, you can use:
session.Query<Collection>("Raven/DocumentCollections")
.Where(x=>x.Name == "Posts")
.FirstOrDefault();
That will give you the result you want.