Rooms per user in matrix synapse database - matrix-synapse

How can I get the total number of matrix rooms a user is currently joined using the synapse postgres database? (excluding those rooms the user has left or been kicked, or been banned from)

I spent several hours looking for this, so I think maybe it can help others.
You can get the number of rooms a user is currently joined querying the table user_stats_current:
SELECT joined_rooms FROM user_stats_current WHERE user_id='#myuser:matrix.example.com';
And if you want to get specifically the ids of the rooms the user is currently joined, you can use the table current_state_events like in this query:
SELECT room_id FROM current_state_events
WHERE state_key = '#myuser:matrix.example.com'
AND type = 'm.room.member'
AND membership = 'join';
Even further, if you want not only the room id but the room name as well, you can add the table room_stats_state like in this other query:
SELECT e.room_id, r.name
FROM current_state_events e
JOIN room_stats_state r USING (room_id)
WHERE e.state_key = '#myuser:matrix.example.com'
AND e.type = 'm.room.member'
AND e.membership = 'join';

Related

PostgreSQL: How to check if a list is contained in another list?

I'm working with PostgreSQL 13.
I have two tables like this:
permission_table
name
permission
Ann
Read Invoice
Ann
Write Invoice
Ann
Execute Payments
Bob
Read Staff data
Bob
Modify Staff data
Bob
Execute Payroll
Carl
Read Invoice
Carl
Write Invoice
risk_table
risk_id
permission
Risk1
Read Invoice
Risk1
Write Invoice
Risk1
Execute Payments
Risk2
Read Staff data
Risk2
Modify Staff data
Risk2
Execute Payroll
I'd like to create a new table containing the names of the employees of the first table whose permissions are pointed as risks in the second table. After the execution, the results should be like this:
name
risk_id
Ann
Risk1
Bob
Risk2
Since Carl only has two of the three permissions belonging to Risk2, he will not be included in the results.
My first brute force approach was to compare the list of permissions belonging to a risk to the permissions belonging to an employee. If the first list is included in the second one, then that combination of employee/risk will be added to the results table.
INSERT INTO results_table
SELECT a.employee, b.risk_id FROM permission_table a, risk_table b WHERE
((SELECT permission FROM risk_table c WHERE b.permission = c.permission ) EXCEPT
(SELECT permission FROM permission_table d WHERE a.employee=d.employee)
) IS NULL;
I'm not sure if the results could be correct using this approach, because if the tables are big, it takes a very long time even if I add a WHERE clause limiting the query to just one employee.
Could you please help?
One way of approaching this one is by
computing the amount of permissions for each "risk_id" value
joining the "permissions" and "risks" table with counts on matching "permission" values
making sure that the distinct count of permissions for each triplet "<permissions.name, risks.risk_id, risks.cnt>" corresponds to the full amount of permissions.
WITH risks_with_counts AS (
SELECT *, COUNT(permission) OVER(PARTITION BY risk_id) AS cnt
FROM risks
)
SELECT p.name, r.risk_id
FROM permissions p
INNER JOIN risks_with_counts r
ON p.permission = r.permission
GROUP BY p.name, r.risk_id, r.cnt
HAVING COUNT(DISTINCT r.permission) = r.cnt
Carl won't be included in the output as he doesn't have all permissions from "risk_id = 'Risk 1'"
Check the demo here.

Result pagination for bulk API with MongoDB

How does results pagination work for bulk API with MongoDB?
API endpoint(just for context):
/team/listTeamsForUsers
Input:
{
"userIds": ["userId1", "userId2", "userId3"...],
"options": {
"pageSize": 10,
"pageIndex": 0
}
}
A user can be associated with multiple teams. Hence the API needs ability to paginate the results, based on pageSize and pageIndex.
Pagination is possible for single userId input. How do I support pagination for multiple inputs?
Example use case:
User01 is associated to 10 teams.
User02 is associated to 20 teams.
when pageSize=10 and pageIndex=0
Teams 1-10 related to User01 should be returned.
when pageSize=10 and pageIndex=1
Teams 1-10 related to User02 should be returned.
when pageSize=10 and pageIndex=2
Teams 11-20 related to User02 should be returned.
It would be great to see examples of such implementation.
Any suggestions?
Assumptions:
I suppose a user can be a member in multiple teams and a team has multiple members. Therefore, users and teams are in a many to many relationship.
I further assume you have a junction table that maps from userId to teamId in order to model the above relationship.
Table structures:
Users table : id | name
Teams table : id | name
UsersTeams : userId | teamId
Considering you get a list of userId as input, a SQL snippet for paging the teams associated with those users would look as follows (please note I did not test the below snippet).
select distinct t.name
from team t, user u, userTeam ut
where t.id = ut.teamId and u.id = ut.userId and u.id in (1, 2)
order by t.name desc
limit 0, 10;
The parameters passed to limit are the pageIndex*pageSize and (pageIndex+1)*pagSize.
The parameters passed to in are the userIds you get from the endpoint.
Although this approach is easy to understand and implement, it does not have the best performance. Please see https://www.xarg.org/2011/10/optimized-pagination-using-mysql/ for paging optimizations for MySQL (although you probably can translate most of that to any SQL database).

OrientDB query for nodes connected to origin by multiple ways

For example, I have employee managing particular country and particular company. I want to query only accounts which are in countries AND companies managed by the given employee. Ideas? Performance issues to be aware of?
Gremlin query is acceptable, also!
This seems to work:
select from Account where
#rId in
(select expand(out('managingCountry').in('inCountry')).#rId
from Employee where userId = 3)
AND
#rId in
(select expand(out('managingCompany').in('inCompany')).#rId
from Employee where userId = 3)
Remains if someone has the better solution

How does a self join table decide what to display when conditions are "identical"

I have a simple chat table. The chat table has a user_id column and a recipient_id column and a boolean agrees_to_chat column.
What I'd like to do, is display the users for which user 1 wants to chat with and whom all other users also want to chat with user 1.
(Note that there will be cases where 1 agrees to chat with 2, but 2 has not gone online to signal a preference yet. Obviously in those cases I don't want a chat to show up.)
Here's what I've come up with so far.
SELECT c1.user_id, c1.recipient_id, c2.user_id, c2.recipient_id FROM chats c1, chats c2
WHERE c1.recipient_id = c2.user_id
AND c1.user_id = c2.recipient_id
AND c2.user_id=1
AND c2.agrees_to_chat=true
AND c1.agrees_to_chat=true
For some reason setting c2.user_id = 1 results in what I want: records where user_id = 1, along with people who have agreed to chat listed in the recipient_id column.
However if I set it to c1.user_id=1 I get the same results flipped over. Namely, now my results are still people who have agreed to chat, but now the recipient_id = 1 for all results, and the user_id is the different users.
This matters to me because if I want to serve data that shows everyone whose agreed to chat with user 1. But if I decide to reference recipient_id in my code, I need to know that won't change...For example, on my computer I noticed that c2.user_id =1 results in what I want, but in this sql fiddle it seems to be that c1.user_id=1 gets what I need... http://sqlfiddle.com/#!15/799a9/2
So what's going on here? Is there something I'm not understanding about my query? Alternatively is there a better query for what I'm trying to achieve?
You don't need all 4 columns, since you already know 1st and 4th (and 2nd and 3rd) will be equal. Use SELECT c2.user_id, c2.recipient_id FROM ... or SELECT c1.user_id, c1.recipient_id FROM .... In case you actually need several copies of the same column from the self-joined tables, you can give names to them: SELECT c1.user_id AS user_id1, c1.recipient_id AS recipient_id1, c2.user_id AS user_id2, c2.recipient_id AS recipient_id2 FROM ...

products and configurable_products in postgresql

I have a Product table and a ConfigurableProduct table.
If there are several variations of the same product like a shirt in different colors I create a ConfigurableProduct.
When a user is looking at the catalog he should see a list of products unless there is a ConfigurableProduct, then he should see it with a select box for each variations.
How do I structure the tables for Product and ConfigurableProduct and how do I query the db so I can page through the results?
Thanks
I am going to answer this as if you do not have tables created. I am not sure if that is true though.
The following is a simple example, but I assume you have more data.
products
id
name
configurable_products
id
variation
product_id REFERENCES products(id)
You can just make the configurable products a reference to products.
If you want a listing of products with their configurations then you can do:
select p.name, c.variation
from products p left outer join configurable_products c
on (p.id = c.product_id);
Of course you can just search for all the configurable_products based on the product id too when needed.
As for the paging part of your question you will have to clarify what you mean. You can use limit to limit results if you don't want to get everything at once.