Subsonic 3.0 How to retrieve all users that belong to specific group in a many to many relationship - subsonic

Lets say I have a many-to-many relationship:
Group table
User table
group_user table which is a many to many table
Given the group name I would like to find all the users that belong to this group.
How can I do this with subsonic 3.0?
IQueryable<group_user> groupUser= group_user.All();
Is it possible from groupUser to get all users who belong to a specific group say group 1?
Is there any other way

Use a linq statment.
something like (very rough):
var users = from gu in group_user.All()
join g on group.All()
join u on user.All()
where g.Name = "My Group"
select u;
If you provide me with your schema I'll be able to knockup a working example.

Related

Including One-To-One association from both sides

I have two models that need to be connected in a one-to-one association: Coach and Team. A team only has one coach and a coach only has one team.
I need to be able to include from both sides: sometimes I query the Coach and include the Team, sometimes I query the Team and include the Coach.
Now I'm not sure: do I need to create reference columns on each table (CoachId in table "Teams" and TeamId in table "Coaches")?
I have tried creating those two columns and established the association like so:
module.exports = models => {
models.Coach.hasOne(models.Team)
models.Team.belongsTo(models.Coach)
}
But for some reason, when I'm creating a Coach and setting the existing TeamId, the TeamId column stays empty. Also, even if it would have been filled, it feels odd to also have to update the Coach row with the correct TeamId.
Can it all be accomplished in one write and then be queried from both sides as suggested above? Feels like I still have not understood something fundamental about Sequelize, even after working with it for a while.
Thanks!
to query from both sides, you need to use a through table
module.exports = models => {
models.Coach.hasOne(models.Team)
models.Team.belongsTo(models.Coach, {through: 'TeamCoach'})
}
TeamCoach will have primary keys from both tables linked such that it can allow for a bi directional query.

Cloudant/Couchdb Architecture

I'm building an address-book app that uses a back-end Cloudant database. The database stores 3 types of documents:
-> User Profile document
-> Group document
-> User-to-Group Link document
As the names of the document go, there are users in my database, there are groups for users(like whatsapp), and there are link documents for each user to a group (the link document also stores settings/privileges of that user in that group).
My client-side app on login, queries cloudant for the user document, and each group document using view collation over the link documents of that user.
Then using the groups that I have identified above, I find all the other users of that group.
Now, the challenge is that I need to monitor any changes on the group and user documents. I am using pouchdb on the app side, and can invoke the 'changes' API against the ids of all the group and user documents. But the scale of this can be maybe 500 users in each group, and a logged in user being part of 10-50 groups. That multiplied to 1000s of users will become a nightmare for the back-end to support.
Is my scalability concern warranted? Or is this normal for cloudant?
If I understand your schema correctly, you documents of this form:
{
_id: "user:glynn",
type: "user",
name: "Glynn Bird"
}
{
_id: "group:Developers",
type: "group",
name: "Software Developers"
}
{
_id: "user:glynn:developers"
}
In the above example, the primary key's sorting allows a user and all of its memberships to be retrieved by using startkey and endkey parameters do the database's _all_docs endpoint.
This is "scalable" in the sense that if is efficient for Cloudant retrieve data from a primary or secondary index because the index is held in a b-tree so data with adjacent keys is store next to each other. A limit parameter can be used to paginate through larger data sets.
yes the documents are more or less how you've specified.
Link documents are as follows:
{
"_id": <AutoGeneratedID>,
"type": "link",
"user": user_id,
"group": group_id
}
I've written the following view map function:
if(type == "link") {
emit(doc.user, {"_id": doc.user});
emit([doc.user, doc.group], {"_id": doc.group});
emit([doc.group, doc.user], {"_id": doc.user});
}
using the above 3 indexes and include-docs=true, 1st lets me get my logged-in user document, 2nd lets me get all group documents for my logged-in user (using start and end key), and 3rd lets me get all other user documents for a group (using start and end key again).
Fetching the documents is done, but now I need to monitor changes on users of each group, for this, don't I need to query the changes API with array of user ids ? Is there any other way ?
Cloudant retrieve data from a primary or secondary index because the
index is held in a b-tree so data with adjacent keys is store next to
each other
Sorry, I did not understand this statement ?
Thanks.
Part 1.
I recommend to get rid of the "link" type here - it's good for SQL world, but not for CouchDb.
Instead of this, it is better to utilize a benefit of Document Storage, i.e. store user groups in property "Groups" for "User"; and property "Users" for "Group".
With this approach you can set up filtered replication to process only changes of specific groups and these changes will already contain all the users of the group.
I want to notice, that I made an assumption, that number of groups for a user and number of groups is reasonable (hundreds at maximum) and doesn't change frequently.
Part 2.
You can just store ids in these properties and then use Views to "join" other data. Or I was also thinking about other approach (for my use case, but yours is similar):
1) Group contains only ids of users - no views needed.
2) You create a view of each user contacts, i.e. for each user get all users with whom he has mutual groups.
3) Replicate this view to client app.
When user opens a group, values (such as names and pics of contacts are taken from this local "dictionary").
This approach can save some traffic.
Please, let me know what do you think. Because right now I'm working on designing architecture of my solution. Thank you!)

How to fetch data from relationship in Core Data in iOS 8?

I have two entities Employee and Department. Both are related with Relationship i.e., 1-to-M and M-to-1. Dept is having attribute called MANAGERID representing the employee Id who is the manager of that dept.
Now i need to fetch DeptName and the Manager Name. How to write the Predicate Format String ?
NOTE: I am working in iOS 8.3 with Xcode 6.3 and Swift 1.2
Thanks in Advance.
If you follow the usual setup described in Apple's documentation, there is no need for ids. To access the department of an employee
let department = employee.department
To get all employees of a department
let employees = department.employees // returns NSSet or [Employee]
Following the design pattern of object graphs, rather than holding a manager id in the Department object, you should just have a one-to-one relationship with the manager.
let manager = department.manager // returns an Employee
This means that you need a separate relationship for the manager:
Department.employees <----->> Employee.department
Department.manager <------> Employee.managedDepartment
Also note that an all-caps attribute name like MANGAERID is illegal in Core Data.

JPQL query with ManyToMany

I have two entity objects, USER and GROUP. GROUP contains a ManyToMany relationship to USER, but that relationship is not bidirectional.
My problem is that I need to find out all of the USERs that are members of a list of GROUPs. If I could reverse the relationship so that the USER contained the relationship to GROUP, I could do this easily, but I can't seem to figure out how to write the JPQL to go the other way.
Can someone out there point me in the right direction?
Thanks
The following seems to work:
select distinct u from User u, Group grp where grp in (?1) and u member of grp.users

How to implement role-based security in T-SQL?

I am developing a stored proc for an SSRS 2008 report, but I want to limit the data output according to the role of the user running the report. How do I do this? What I wanted to do was to retrieve the Windows user name and filter the records based on this, but users are using the "sa" account to login to the server. So now I'm thinking I should use the AD login instead.
I've also seen how security can be setup in SSRS instead of the T-SQL sproc so that users have access to appropriate folders. But this second approach sounds much more cumbersome since we have many different reports and because I want users to have access to all reports, but just access to different parts of the data.
Is it better to implement security via SSRS groups and folders on the report server or else inside the T-SQL sproc?
I looked at that link for the "(=User.UserID)" solution, but am having trouble implementing this. What I did: I created a dataset in SSRS by selecting the text query:
select people_id from people_rv where last_name like 'd%'
This returns a list of people_id's
Then, I created a new parameter and set it equal to the above dataset for available values. And I made it Text datatype and allow Null and Blank values. No default values. Finally, I set visibility for the tablix:
=iif(Parameters!staff_id.Value in (select people_id from users),1,0)
But this generates an error. How can I reformulate this tablix expression?
Regardless of the method used to access the data source you can still retrieve the user ID (=User.UserID) that is accessing the report. Set this to an internal parameter in SSRS, and you can then incorporate security into your queries very easily.
Check out the answer to this question submitted a few minutes after yours.
More specific details of implementation using BIDS and SSRS 2008R2 (2008 should be identical)
Create a parameter, let's call it "UserID". Type should be Text, and parameter visibility should be "Internal"
The Default value for this parameter should be set to Specify Values, and add a value: =User.UserID
As a temporary debugging aid, drag the parameter to your design surface to create a textbox with the value of the UserID. (Preview the report and see that this is getting set to your user ID if you'd like to confirm.)
Create a dataset for your next parameter: Create a dataset that will only list available values for this user. The query might be something like:
SELECT
CategoryName,
CategoryID
FROM
Categories c
INNER JOIN
CategoryPermissions cp
ON c.ID = cp.CategoryID
INNER JOIN
Users u
ON cp.UserID = u.People_ID
WHERE u.WindowsAccount = #UserID
Set up a parameter that you will display to the user. It should get its available values from the query in the previous step.
Set up your main dataset. It should both use the value of the parameter from step 5 as well as the permissions query from step 4. Something like:
SELECT
*
FROM
Products p
INNER JOIN
Categories c
ON p.CategoryID = c.ID
INNER JOIN
CategoryPermissions cp
ON c.ID = cp.CategoryID
INNER JOIN
Users u
ON cp.UserID = u.People_ID
WHERE u.WindowsAccount = #UserID
AND c.CategoryName in ( #Categories )
(This double checks that the user has the permission to see this category.)

Resources