Guava group by and order by members - guava

I want to group and order the elements by certain members in guava instead of sql.
sql = "SELECT * FROM players GROUP BY club, country ORDER BY goals DESC";
When i try grouping by Multiset, it takes the entier class as a parameter and gives me back the list.
Multiset<Player> multiset = HashMultiset.create();
for (Player player: players) {
multiset.add(player);
//multiset.add(player, 1);
}
What is the correct way to do this ?

You can use guava tables, for multiple key access.

Related

OrientDB select record count from all graph classes

Any way to get record count for each graph class (V, E and their subclasses)?
I tried to build query in SQL format for current case:
SELECT #class, count(*) FROM V GROUP BY #class
SELECT #class, count(*) FROM E GROUP BY #class
But using count() + GROUP BY is extrimply slow combination.
While console command list classes works fast and return values for count of records in each class (field RECORDS), how to extract this counts via SQL query (or via OrientJS API)?
The main idea is find a way to:
Get list of all classes if database
Get count of records that stored in each class
Technical details
In OrientDB functions you have access to orient variable that have .getDatabase() method. And this method return JAVA ODatabaseDocumentTx class instance. This class provides the method .countClass(className) that returns the number of the records of the class className (method documentation) and it works realy fast.
Solution
Create function in OrientDB Studio with name "getClassCounts", language "javascript", idempotent: true:
var db = orient.getDatabase();
var classesRawInfo = db.getMetadata().getImmutableSchemaSnapshot().getClasses().toArray();
var classesList = {};
var i = classesRawInfo.length;
while(--i) {
var className = classesRawInfo[i].name;
classesList[className] = db.countClass(className);
}
return classesList;
Executing:
via SQL: SELECT getClassCounts()
I think it's not possible, also because it wouldn't so fast as in the console

Possible to do two Group Bys and an if count check in one LINQ lambda statement?

Kind of a specific question but I wasn't sure how to approach it. I've got a list of rooms, that I am trying to group first by type, then by owner. I am doing this to check if there are duplicate rooms for a given owner and type (which shouldn't be possible so I need to prune them out). Right now my code looks like this:
IQueryable<IGrouping<Guid, Room>> allRoomsByOwner = _dbContext.Rooms.GroupBy(x => x.OwnerId);
List<Room> duplicates = new List<Room>();
foreach (IGrouping<Guid, Room> roomsByOwner in allRoomsByOwner)
{
IEnumerable<IGrouping<Guid, Room>> roomsOfOwnerByType = roomsByOwner.ToList().GroupBy(x => x.TypeId);
foreach (IGrouping<Guid, Room> grouping in roomsOfTypeByType)
{
if (grouping.Count() > 1)
{
duplicates.AddRange(grouping.ToList());
}
}
}
I'm just wondering if it's possible to put this all into one LINQ statement? I've got similar things before, but not quite this complex and not using two group bys. Thanks.
You can group by multiple columns ( OwnerId and TypeId) and flatten the groups with more than one elements (using the SelectMany method) to get the duplicates:
var duplicates = _dbContext.Rooms.GroupBy(x => new{x.OwnerId,x.TypeId})
.Where(g=>g.Count()>1)
.SelectMany(g=>g.Skip(1))// If you like you can skip the first element as representative of the group and the treat the rest as a duplicate.
.ToList();

Entity Framework: How do I invoke pairs of entities from a raw query

For instance, I have a query:
SELECT * FROM
persons
LEFT JOIN vehicles
ON persons.Id = vehicles.OwnerId
I would like execute this query on an EF data context and have array of pairs "person-vehicle". how do I do it?
Another example:
SELECT persons.*, COUNT(vehicles.*) as cnt FROM
persons
JOIN vehicles
ON persons.Id = vehicles.OwnerId
GROUP BY vehicles.Id
Here I want to have a dictionary of a person as a key and number of vehicles he owns as a value.
I know that these quesies are simple enough and it's better to avoid raw sql in these cases. But I want to know possibilities of raw query handling, because real life queries can be much more complex.
You probably want to do some reading ion LINQ to Entities. https://msdn.microsoft.com/en-us/library/vstudio/bb386964(v=vs.100).aspx
The first one is pretty basic:
var persons = context.Persons
.Include(p => p.Vehicles)
.ToList();
The second one is a little more advanced:
var persons = context.Persons
.Select(p => new { Person p, VehicleCount = p.Vehicles.Count() }
.ToList();
You could also do a group by which is described in the link.

Category tree structure with node count using JPA

I have a category tree structure, using JPA with eclipse link.
Each category in the tree includes items, and I want to select all categories along with their items count.
The code I inherited used to calculate the number of items offline, and update the category, and use the cool JPA trick for selecting the categories like so:
#Entity
#Table(name = "categories")
#NamedNativeQuery(name = "topLevel", query = "SELECT categories.* FROM categories WHERE categories.parent_id IS NULL")
public class Category {
#Id
private Long id;
private String name;
private Integer item_count;
private Long parent_id;
#JoinColumn(name = "parent_id")
private List<Categories> categories;
}
When running the native query - I get all the categories populated in the tree structure.
However, now I have a new filter that doesn't allow the user to see all the items in the category. So I can no longer calculate the items offline.
I tried to use a join so I can calculate it online, like this:
#NamedNativeQuery(name = "topLevel", query = "SELECT categories.*, count(*) as item_count FROM categories, items_to_categories WHERE categories.id = items_to_categories.category_id and some_user_specific_query and categories.parent_id IS NULL GROUP BY categories.id")
but this doesn't populate the lower levels with the right items count.
Since I am using Eclipse Link, I can't use a formula field that is not supported in this JPA implementation.
Any ideas on how to change my model in order to get it to work?
Thanks in advance!
If you want an Item count you can either query for it, such as using JPQL. This will return an Object[] including the Category and its Integer item count. If you want to use a native SQL query, then you will need to use a SqlResultSetMapping.
If you want the item count in Category, then you could define a database VIEW that makes this appear as a column and map to the view.
Another option is to map the items of the Category, then to get the item count, just access the size() of the items in Java (you could use join or batch fetching to load the items efficiently).

Entity Framework, How to include related entities in this example

I have a table AccountSecurity which is a many-to-many table that relates Account entities and Securities. When I write the query below it returns all Securities that satisfy the where clause. However each Security instance in the list no longer has the reference to the AccountSecurity it came from. So when I do list[0].AccountSecurity it is empty. Is there anyway to include that information? I know I can rewrite the query to return AccountSecurities instead and use .Include("Security") on that, but I wonder if it can be done another way.
var list = (from acctSec in base.context.AccountSecurities
where acctSec.AccountId == accountId
select acctSec.Security).ToList();
UPDATE
Of course if I do two queries the graph gets populated properly, there has to be a way to do this in one shot.
var securities = (from acctSec in base.context.AccountSecurities
where acctSec.AccountId == accountId
select acctSec.Security).ToList();
//this query populates the AccountSecurities references within Security instances returned by query above
var xref = (from acctSec in base.context.AccountSecurities
where acctSec.AccountId == accountId
select acctSec).ToList();
var list = (from sec in base.context.Securities
.Include("AccountSecurity")
where sec.AccountSecurities.Any(as => as.AccountId == accountId)
select sec).ToList();
Try this:
var list = (from acctSec in base.context.AccountSecurities.Include("Security")
where acctSec.AccountId == accountId
select acctSec).ToList();
Then simply use the Security property as needed, and since it's read at the same time AccountSecurities is (single SQL with join), it will be very efficient.