What is the proper aproach for agregational like queries? - xodus

looking into Java query approach or Kotlin based DNQ can't see how to make queries similar to 'group by' ... What is a proper approach for such queries? E.g. when I have invoices entities and I would like to group these by company name and sum of sales.

Something like this can help you achieve an emulated "GROUP BY":
entityStore.executeInTransaction(
new StoreTransactionalExecutable() {
#Override
public void execute(#NotNull final StoreTransaction txn) {
txn.getEntityTypes().forEach(type -> {
EntityIterable result = txn.getAll(type);
long count = result.count();
});
}
});
Essentially what this does is it queries all entity types and then do a count, similar to what GROUP BY does. From here you can just create a Map or something to put both the entity type and count in the map.

Related

How to only return subset of larger query in GraphQL without returning the whole thing?

I am new to GraphQL and trying to understand how to only return a subsection of the resulting query. For example, here is my cypher query in Neo4j:
MATCH (u:User)-[HAS_FRIEND]-(f:User)
WHERE u.name = "Joe"
RETURN f.name
Notice how the above query only returns the friend names.
GraphQL
Here's a sample of GraphQL version of the above cypher query.
Input
{
"where": {
"name": "Joe"
}
}
Query
query Query($where: NameWhere) {
names(where: $where) {
name
friends {
name
}
}
}
Expected Output
Obviously, I expect output to include friends name array and the name of the user having the friend. But, what if I only want the friends array like the cypher query gives me?
While this is a simple example, I am using a graph database that has a series of connections and my nesting is looking pretty deep, but I only really need a subquery from the result. A great example is with localization - I don't need the country and language (locale), etc. in every query; I only want the subquery result (e.g. the spelling in UK/ENG is colour and in US/ENG is color).
Neo4j offers a Javascript GraphQL library that is able to handle your use case (and many more)!
Please have a look at the documentation for information on how to get started. See even the example queries, where this one is fairly close to what you are looking for.
Anyhow, the GraphQL query provided above, using the #neo4j/graphql library, could look like so:
query Query {
users (where: { name: "Joe" }) {
friends {
name
}
}
}
(Note that the where parameter ("Joe") is provided in-line in this case)

Grails query: Get list of associated objects

I have a many-to-many relationship:
class Project {
Set<PrincipalInvestigator> pis
:
static hasMany = [ pis:PrincipalInvestigator ]
}
class PrincipalInvestigator {
String name
:
}
I want a query that returns a unique and sorted list of PIs that belong to a pre-defined list of projects.
A naive approach is to iterate thru the projects, and iterate thru their list of PIs, while removing the dupes. The code to do this is trivial, but it is slow.
So far, the best working solution I could come up with is:
def pi_ids = Project.createCriteria().list{ // find unique list of PI IDs
// project filters here, not relevant to the question
createAlias('pis', 'aka_pis', JoinType.LEFT_OUTER_JOIN)
isNotNull('aka_pis.id')
projections {
distinct('aka_pis.id')
}
}
def pi_list = PrincipalInvestigator.createCriteria().list{ // get PIs from list of IDs
inList('id', pi_ids)
order('name', 'asc')
}
My solution is one order of magnitude faster, but it's still 2 distinct queries. Is there a way to get the same result in a single query?
Using executeQuery makes queries as this alot easier. Something along the following should work:
PrincipalInvestigator.executeQuery("select distinct p.pis from Project p where p.id in :projectIds",
[projectIds: [1,2,3]])
The solution to my problem is this HQL:
PrincipalInvestigator.executeQuery(
"select distinct pi from Project p inner join p.pis as pi where p.id in :projectIds order by pi.name",
[projectIds:[1,2,3]])
This solution allows for sorting of the distinct results and the inner join trims all the null instances. Thanks to cfrick for putting me on the right track.

MVC more specified models should be populated by more precise query too?

If you have a Car model with 20 or so properties (and several table joins) for a carDetail page then your LINQ to SQL query will be quite large.
If you have a carListing page which uses under 5 properties (all from 1 table) then you use a CarSummary model. Should the CarSummary model be populated using the same query as the Car model?
Or should you use a separate LINQ to SQL query which would be more precise?
I am just thinking of performance but LINQ uses lazy loading anyway so I am wondering if this is an issue or not.
Create View Models to represent the different projections you require, and then use a select projection as follows.
from c in Cars
select new CarSummary
{
Registration = c.Registration,
...
}
This will create a query that only select the properties needed.
relationships will be resolved if they are represented in the data context diagram (dbml)
select new CarSummary
{
OwnerName = c.Owner.FirstName
}
Also you can nest objects inside the projection
select new CarSummary
{
...
Owner = new OwnerSummary
{
OwnerName = c.Owner.FirstName,
OwnerAge = c.Owner.Age
}
...
}
If you are using the same projection in many places, it man be helpful to write a method as follows, so that the projection happens in one place.
public IQueryable<CarSummary> CreateCarSummary(IQueryable<Car> cars)
{
return from c in cars
select new CarSummary
{
...
}
}
This can be used like this where required
public IQueryable<CarSummary> GetNewCars()
{
var cars = from c in Cars
select c;
return CreateCarSummary(cars);
}
I think that in your case lazy loading doesn't bring much benefit as you are going to use 1 property from each table, so sooner or later to render the page you will have to perform all the joins. In my opinion you could use the same query and convert from a Car model to a CarSummary model.
If performance is actually a concern or an issue currently, you should do a separate projection linq query so that the sql query only selects the 5 fields you need to populate your view model instead of returning all 20 fields.

Compare associations between domain objects in Grails

I am not sure if I am going about this the best way, but I will try to explain what I am trying to do.
I have the following domain classes
class User {
static hasMany = [goals: Goal]
}
So each User has a list of Goal objects. I want to be able to take an instance of User and return 5 Users with the highest number of matching Goal objects (with the instance) in their goals list.
Can someone kindly explain how I might go about doing this?
The easiest and most efficient way to achieve this is using plain SQL. Assuming you have these tables
users [id]
goals [id, description]
user_goals [user_id, goal_id]
You can have the following query to do what you need:
set #userId=123;
select user_id, count(*) as matched from user_goals
where user_id!=#userId
and goal_id in (select ug.goal_id from user_goals ug where ug.user_id=#userId)
group by user_id order by matched desc limit 5;
This takes a user id and returns a list of other users with matching goals, sorted by the number of matches. Wrap it up in a GoalService and you're done!
class GoalService {
def findUsersWithSimilarGoals(user) {
// ...
}
}
It may also be possible to do this with criteria or HQL, but with queries like this it's usually easier to use SQL.
If you're looking for a simple match, perhaps the easiest way would be to do a findAll for each Goal and then count the number of results that each other User appears in:
Map user2Count = [:]
for (goal in myUser.goals){
for (u in User.findAllByGoal(goal)){
def count = user2Count.containsKey(u) ? user2Count.get(u) : 0
count++
user2Count.put(u, count)
}
}
// get the top 5 users
def topUsers = user2Count.entrySet().sort({ it.value }).reverse()[0..5]
This may be too slow, depending on your needs, but it is simple. If many users share the same goals then you could cache the results of findAllByGoal.

Search Database - ASP.NET MVC C#

I'm attempting to implement complete search functionality in my ASP.NET MVC (C#, Linq-to-Sql) website.
The site consists of about 3-4 tables that have about 1-2 columns that I want to search.
This is what I have so far:
public List<SearchResult> Search(string Keywords)
{
string[] split = Keywords.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
List<SearchResult> ret = new List<SearchResult>();
foreach (string s in split)
{
IEnumerable<BlogPost> results = db.BlogPosts.Where(x => x.Text.Contains(s) || x.Title.Contains(s));
foreach (BlogPost p in results)
{
if (ret.Exists(x => x.PostID == p.PostID))
continue;
ret.Add(new SearchResult
{
PostTitle= p.Title,
BlogPostID = p.BlogPostID,
Text=p.Text
});
}
}
return ret;
}
As you can see, I have a foreach for the keywords and an inner foreach that runs over a table (I would repeat it for each table).
This seems inefficent and I wanted to know if theres a better way to create a search method for a database.
Also, what can I do to the columns in the database so that they can be searched faster? I read something about indexing them, is that just the "Full-text indexing" True/False field I see in SQL Management Studio?
Also, what can I do to the columns in
the database so that they can be
searched faster? I read something
about indexing them, is that just the
"Full-text indexing" True/False field
I see in SQL Management Studio?
Yes, enabling full-text indexing will normally go a long way towards improving performance for this scenario. But unfortunately it doesn't work automatically with the LIKE operator (and that's what your LINQ query is generating). So you'll have to use one of the built-in full-text searching functions like FREETEXT, FREETEXTTABLE, CONTAINS, or CONTAINSTABLE.
Just to explain, your original code will be substantially slower than full-text searching as it will typically result in a table scan. For example, if you're searching a varchar field named title with LIKE '%ABC%' then there's no choice but for SQL to scan every single record to see if it contains those characters.
However, the built-in full-text searching will actually index the text of every column you specify to include in the full-text index. And it's that index that drastically speeds up your queries.
Not only that, but full-text searching provides some cool features that the LIKE operator can't give you. It's not as sophisticated as Google, but it has the ability to search for alternate versions of a root word. But one of my favorite features is the ranking functionality where it can return an extra value to indicate relevance which you can then use to sort your results. To use that look into the FREETEXTTABLE or CONTAINSTABLE functions.
Some more resources:
Full-Text Search (SQL Server)
Pro Full-Text Search in SQL Server 2008
The following should do the trick. I can't say off the top of my head whether the let kwa = ... part will actually work or not, but something similar will be required to make the array of keywords available within the context of SQL Server. I haven't used LINQ to SQL for a while (I've been using LINQ to Entities 4.0 and nHibernate for some time now, which have a different set of capabilities). You might need to tweak that part to get it working, but the general principal is sound:
public List<SearchResult> Search(string keywords)
{
var searcResults = from bp in db.BlogPosts
let kwa = keywords.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);
where kwa.Any(kw => bp.Text.Contains(kw) || bp.Title.Contains(kw))
select new SearchResult
{
PostTitle = bp.Title,
BlogPostID = bp.BlogPostID,
Test = bp.Text
};
return searchResults.ToList();
}

Resources