SailsJS manually populate records using Model.query - sql

lets say i have this example as my app
http://sailsjs.org/#!/documentation/concepts/ORM/Associations/OnetoMany.html
For some big reasons(complicated) I cannot use Model.populate() and I'm stuck in using Model.query()
Does anyone know how to get the result as User.find().populate('pets') Using Model.query() Please
Thank you

You can do it like waterline adapters do to populate OneToMany:
Retrieve parents : select * from user ...
Retrieve children for each parent in only one query to not overload DBMS:
select * from pet where user = user1.id union select * from
pet where user = user2.id union ... union select * from pet where user
= userN.id.
Regroup children by parentPk(you can use lodash or underscore.js functions to do it) Ex:
users.forEach(function(user){
user.pets = _.filter(pets,function(pet){
return pet.user === user.id;
});
});

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.

Is there a way to combine where and where.not into one condition in Rails?

I have an Event model, that has user_id inside it. I want to select all objects of this model, with specified user_id but not including specific events. So I can do it with a query like that:
Event.where(user_id: user.id).where.not(id: id)
But can I combine these 2 where functions into one?
I know that if I need to find, for example, events with specified ids and user_ids, I can do it this way:
Event.where(user_id: user_id).where(id: id)
and I can compact it using one where call instead of two:
Event.where(user_id: user_id, id: id)
but can I do the same thing if I am using where and where.not?
You can gather
Event.where(user_id: 1) + Event.where.not(id: 2)
or deny a parameter
Event.where(user_id: 1).where.not(id: 2)
You can write as per below to add where and where.not :
Event.where(
"user_id = ? AND id != ?",
user.id,
id
)
so if user_id = 1 and id = 2
than this will return records with user_id 1 and without id 2 :)
try this,you can create two scopes and calling then in chain
scope :with_user, ->(user) {user_id: user.id}
scope :excluded_event, ->(event_ids) { where.not(id: event_ids) }
Event.with_user(user).excluded_event(event_ids)

OrientDB Select on two related vertex

I have a scenario as shown below ,
I want to query the database so I get the following result,
User Resource Permissions
Edi Plan A [view]
Where
resource.name = 'Plan A' and user.name = 'Edi'
my query for above is
SELECT name,
out('hasARole').out('ofType').in('isOfType')[name = 'Plan A'].name,
set(out('hasARole').out('hasA').name) as permission
FROM user
WHERE name = 'Edi'
It should display
User Resource Permissions
Adrian Plan A [view,edit, delete]
if I change it to,
Where
resource.name = 'Plan A' and user.name = 'Adrian'
my query for above is
SELECT name,
out('hasARole').out('ofType').in('isOfType')[name = 'Plan A'].name,
set(out('hasARole').out('hasA').name) as permission
FROM user
WHERE name = 'Adrian'
Now above queries work as long as the users don't have another role on another type of resource. e.g. if Edi had Admin role on let's say a resource type of Workspace then the query gives me back all the permissions that an Admin would have , instead of just view as he only has view permission on Plan A
I have used the following graph for my answer. Note that I have corrected some incositencies with your original edges.
I see a number of possible queries for this problem. I am a bit confused why you would want to return the User and Resource in the query, as you probably already have these records due to the fact you use them to create the query. You can't 'nest' the full records in the results either (unless you JSON them). Further to this, querying on the name field, and returning only the name field seem a little nonsensical to me - but maybe you have done so to simplify the question. Regardless, the following queries will get you on your way to your desired results.
My first idea is to run a query to get all of the Roles related to a Resource. We then run a query over these results to filter for the Roles that include the User. This looks like the following;
select from (
select expand(out('isOfType').in('ofType')) from Resource where name = "Plan A"
) where in('hasARole') contains first((select from User where name = "Edi"))
This query correctly returns just the Viewer record for both Edi and Adrian.
My second idea is to run 1 query for the Roles related to a Resource (similar to above), and another for the Roles related to a User, and then find the intersect. This looks like the following, and gives the same results as the query above;
select expand(intersect) from (
select intersect($resource_roles, $user_roles)
let
$resource_roles = (select expand(out('isOfType').in('ofType')) from Resource where name = "Plan A"),
$user_roles = (select expand(out('hasARole')) from User where name = "Edi")
)
Now if you really do want the User, Resource and Permissions all in the 1 result, you can use the following, or a variant of;
select first($user).name as User, first($resource).name as Resource, intersect(resource_roles, user_roles).name as Permissions from (
select $resource.out('isOfType').in('ofType') as resource_roles, $user.out('hasARole') as user_roles
let
$resource = (select from Resource where name = "Plan A"),
$user = (select from User where name = "Edi")
)
or
select first($user).name as User, first($resource).name as Resource, intersect($resource_roles, $user_roles).name as Permissions
let
$resource = (select from Resource where name = "Plan A"),
$resource_roles = (select expand(out('isOfType').in('ofType')) from $parent.$resource),
$user = (select from User where name = "Edi"),
$user_roles = (select expand(out('hasARole')) from $parent.$user)

SQL order by list

Here is part of code for favourited wallpapers:
...
$profile = mysql_fetch_array(mysql_query("SELECT * FROM users WHERE id = $id"));
}
if ($profile['favourites'] != '') {
$from = (($page * $template['fav_wallpaper_limit']) - $template['fav_wallpaper_limit']);
$favourites = substr($profile['favourites'], 2);
/// Tried to join 2 tables, but favourites still displayed by wallpaper id
$sql = mysql_query("
SELECT
*
FROM
wallpapers AS w
JOIN favourites AS f on f.wallpaper_id = w.id
WHERE
w.id IN ($favourites) AND w.published = 1
ORDER BY
f.wallpaper_id LIMIT $from, $template[fav_wallpaper_limit]");
");
Problem is, that it displays wallpapers by the id column that is stored in wallpapers table. While I need to display them by how they wore favourited. The data is stored in users table, and have column favourites for each user with id list of favourited wallpapers.
EXAMPLE:
, 90, 2031, 1, 34, 460, 432, ..., 2013;
Is there any way do grab this tada and order favourites from it?
I think you need to do this within your PHP code:
Read the value of the favourites column;
Explode it into an array;
Iterate through the array, querying the database to get the favourites in the specified order.
The usual way to do this kind of thing is to have a seperate table, say user_favourites with a row for each fovourite for each user that just includes the user id and the favourite id - in this case, with an order factor as well. With the database set up this way, your can execute a query on the new user_favourites table, where user_id is the user id, ordered by the "order factor" to get the favourites in the right order all in one go.
Which database are you using? You might be able to do something like
SELECT _whatever_
FROM favourites
WHERE favourite_id IN (SELECT favourites FROM users)
and it might return the favourites in the correct order. I think the additional table approach is superior, if you can do it that way.

How do I flatten a hierarchy in LINQ to Entities?

I have a class Org, which has ParentId (which points to a Consumer) and Orgs properties, to enable a hierarchy of Org instances. I also have a class Customer, which has a OrgId property. Given any Org instance, named Owner, how can I retrieve all Customer instances for that org? That is, before LINQ I would do a 'manual' traversal of the Org tree with Owner as its root. I'm sure something simpler exists though.
Example: If I have a root level Org called 'Film', with Id '1', and sub-Org called 'Horror' with ParentId of '1', and Id of 23, I want to query for all Customers under Film, so I must get all customers with OrgId's of both 1 and 23.
Linq won't help you with this but SQL Server will.
Create a CTE to generate a flattened list of Org Ids, something like:
CREATE PROCEDURE [dbo].[OrganizationIds]
#rootId int
AS
WITH OrgCte AS
(
SELECT OrganizationId FROM Organizations where OrganizationId = #rootId
UNION ALL
SELECT parent.OrganizationId FROM Organizations parent
INNER JOIN OrgCte child ON parent.Parent_OrganizationId = Child.OrganizationId
)
SELECT * FROM OrgCte
RETURN 0
Now add a function import to your context mapped to this stored procedure. This results in a method on your context (the returned values are nullable int since the original Parent_OrganizationId is declared as INT NULL):
public partial class TestEntities : ObjectContext
{
public ObjectResult<int?> OrganizationIds(int? rootId)
{
...
Now you can use a query like this:
// get all org ids for specific root. This needs to be a separate
// query or LtoE throws an exception regarding nullable int.
var ids = OrganizationIds(2);
// now find all customers
Customers.Where (c => ids.Contains(c.Organization.OrganizationId)).Dump();
Unfortunately, not natively in Entity Framework. You need to build your own solution. Probably you need to iterate up to the root. You can optimize this algorithm by asking EF to get a certain number of parents in one go like this:
...
select new { x.Customer, x.Parent.Customer, x.Parent.Parent.Customer }
You are limited to a statically fixed number of parent with this approach (here: 3), but it will save you 2/3 of the database roundtrips.
Edit: I think I did not get your data model right but I hope the idea is clear.
Edit 2: In response to your comment and edit I have adapted the approach like this:
var rootOrg = ...;
var orgLevels = new [] {
select o from db.Orgs where o == rootOrg, //level 0
select o from db.Orgs where o.ParentOrg == rootOrg, //level 1
select o from db.Orgs where o.ParentOrg.ParentOrg == rootOrg, //level 2
select o from db.Orgs where o.ParentOrg.ParentOrg.ParentOrg == rootOrg, //level 3
};
var setOfAllOrgsInSubtree = orgLevels.Aggregate((a, b) => a.Union(b)); //query for all org levels
var customers = from c in db.Customers where setOfAllOrgsInSubtree.Contains(c.Org) select c;
Notice that this only works for a bounded maximum tree depth. In practice, this is usually the case (like 10 or 20).
Performance will not be great but it is a LINQ-to-Entities-only solution.