I am new to study graph databases (using Neo4j), I am modelling for my project. The business rule is that we need to store the users and devices they used, and this is my current model:
Account A uses device D: (Account A) -[USED]-> (Device D)
Account B also uses device D: (Account B) -[USED]-> (Device D)
=>
(Account A) -[USED]-> (Device D) <-[USED]- (Account B)
In future, account B will use other devices & be related with other accounts.
My questions are:
Is it a good model in this case?
With this model, how to find all associated account with account A?
Thank for you help.
Yes, this model works, as :Account and :Device nodes are distinct in the graph.
As for figuring out what other accounts that are associated with :Account a (only considering the link via using the same device), simple queries should do the trick. Assuming we have :Account(name) in the graph, and that there's an index on this (for fast lookup of :Account nodes by name), we could use this:
MATCH (:Account {name:'A'})-[:USED]->()<-[:USED]-(other:Account)
RETURN DISTINCT other
If :USED relationships always are incoming to :Device nodes, we could simplify this to:
MATCH (:Account {name:'A'})-[:USED*2]-(other:Account)
RETURN DISTINCT other
If we also needed the devices used in common between the two connected account nodes, we could include that as a collection of the nodes between the two linked accounts:
MATCH (:Account {name:'A'})-[:USED]->(device)<-[:USED]-(other:Account)
RETURN other, collect(device) as sharedDevices
Related
I am building a heterogenous graph database looking at organisational structures. The vertices are: people, role, entity and each have different properties.
I want to be able to return properties from the different vertices but can’t seem to get all three vertices and multiple properties from each of them.
Any ideas?
from what I see in your comment
(first name, last name, age) —(fills)—> role (role name, role type, rank) <— (has) — entity (entity name, address, entity type)
You can try:
g.V("person").
has("first name", "Bob").
out("fils").as("a").
in("has").as("b").
select("a", "b").by(valueMap())
I have a graph representation of data with multiple nodes with random relationships
I'm using Neo4j to represent this and using query
Using query
MATCH (a)-[r]->(b)-[r2]->(c)
I'm getting an output where ever A is related with B and B is related with C
But I need to query nodes A and B with any relationship (call as RelationA) and all C following B (with RelationA) with the Same relation as A and B like the following image
if A is connected with more than one B then the expected graph will be like this
You can check the equality of the relationships in the WHERE clause.
MATCH path=(a)-[r]->(b)-[r2]->(c)
WHERE type(r)=type(r2)
RETURN path
P.S.: If you are viewing this result in the Neo4j browser, then it "connects the result nodes" which means it adds extra relationships between nodes that don’t match the criteria. Don’t forget to uncheck the "connect result nodes" option in the from the settings.
I am new to graphs and its very interesting.This question may be noob one but please site some good materials.
I am trying to make a small social Network where each user is a node and has undirected connection with his friend.
Its working fine but now I want to store it in a database.
How can I store the data?How to store all the connected nodes(pointer) of a node.
Is it better to delete the memory after the user log out and read it from database when he logs in or should logging in and logging out shouldnot have any impact on the node?
I know its theoretical. Any references will be really helpful.
Use an actual graph database to store your data.
http://www.neo4j.org/
You can store key/value pairs in a node and you can also store edges that connect nodes.
Then you can use something like Gremlin to query/traverse the graph -https://github.com/tinkerpop/gremlin. See their documentation to download examples and run sample queries: https://github.com/tinkerpop/gremlin/wiki/Getting-Started
An idea of the syntax:
gremlin> // lets only take 'knows' labeled edges
gremlin> v.out('knows')
==>v[2]
==>v[4]
gremlin> // lets do a traversal from the '1' marko vertex to its outgoing edges.
gremlin> // in the property graph world, edges are first class citizens that can be traversed to.
gremlin> v.outE
==>e[7][1-knows->2]
==>e[9][1-created->3]
==>e[8][1-knows->4]
I start at the bottom.
Is it better to delete the memory after the user log out and read it from database when he logs in or should logging in and logging out should not have any impact on the node?
You will need some sort of permanent storage, or your lose all the data you acquired on your first crash/restart that might upset your users a bit.
How can I store the data?
Well without knowing more about this it is difficult however assuming that you have a list of users and each user can have 0 or more friends then i would go with 2 tables.
Users - stores all your user information such as username and password
UsersFriends *- store all the relationships in a UserID -> UserID fashion *
Example
Users Table
UserID Username
1 user2511713
2 abstracthchaos
3 anotheruser
UsersFriends
UserID FriendUserID
1 3
2 3
1 2
Means user2511713 is friends with anotheruser & abstracthchaos and abstracthchaos friends with anotheruser, dependant on your business logic it may also be useful to imply the other way around such that 3 1 is the same as 1 3
My project requirement is something like this:
On Top, there will be Administrator, who will have all d access, first level
Under Administrator, there will be Department Heads, who will have all d access, apart from Creating Department Heads
Under Department Head, there will Other Members, who will be managing their allocated department wise data.
Now, all different department heads will have their own information and members, and all department heads / Members will have access to their own specific records, which they are entering / managing.
Now, with CakePHP's ACL Component, I can divide the roles and their access level, but all department heads can see the other department head's information, as they will have same level of access, and All Other Members can see the other members information on diff departments, as of they will have same level of access.
My project complexity is that - they should be visible only their assigned or created information / data, though they have same level / role assignments as of others.
Can anyone suggest me best suitable option, to manage all these things with already available plug-ins with CakePHP.
I can work by customizing the default ACL Component, but that will take some more amount of time, than what is expected.
Any better ideas / suggestions would be appreciated !
the way i see it, ACL is not that magical. For exemple: ACL could manage the permissions to tell who has access to add/edit/remove a product.. but it wont be able to change a query to filter the products accordingly to the defined permissions (like "users from department A can only see products from department A").. well actually that's a lie, ACL could manage that but it might not be practical, because every time you add a product you'd have to create an ACO, and set the permission in the AROS_ACOS table and since the AROS is a tree structure, so it could easily become a nigthmare, if your planning to query your data
I'd use a group-only ACL to control the access to certain pages/actions and make rules like:
"Department Head can access the page
'products list' and add/delete/modify
products"
"Administrators can access
all pages"
"Other users can access
'products list' and they can add
products but not delete them"
and i'd adjust my queries accordingly to the connected user, so in the controller of 'products list' page, i'd do something like:
If connected user blongs to Department Head then select all products where product.department_id=connected_user.department_id
If connected user is Admin then select all products
if you have too much queries and you dont want to do thousands of if's sentences, you could create a component, a behavior or maybe extend the find() method in the app_model. The idea is to catch all queries and check if one of the models used on the query have field called "department_id", if they do then add the model.department_id=connected_user.department_id condition to the query.
I did that for one website that can be seen in multiple languages and each language has it's own users, data, logs, etc., and there's one Admin that can see all the info.. and it's working great for me =)
Good Luck!
EDITED:
the behavior i use is:
<?php
class LocalizableBehavior extends ModelBehavior {
/**
* Filter query conditions with the correct `type' field condition.
*/
function beforeFind(&$model, $query)
{
/**
* Condition for the paginators that uses joins
*/
if(isset($query['joins']) && !empty($query['joins'])){
foreach($query['joins'] as $key => $joinTable){
if(ClassRegistry::init($joinTable['alias'])->hasField('lang')){
$query['joins'][$key]['conditions'][] = $joinTable['alias'].".lang = '".$_SESSION['lang']."'";
}
}
}
/**
* condition for the normal find queries
*/
if($model->hasField('lang') && $model->name != "User"){
$query['conditions'][$model->name.'.lang'] = $_SESSION['lang'];
}
return $query;
}
}
?>
it's quite simple really, i change the query to add a condition to match to the current language ($_SESSION['lang']). In the controller all i need to do is to attach the LocalizableBehavior and use find method as usual:
$this->Products->find('all');
Preface: I don't have experience with rules engines, building rules, modeling rules, implementing data structures for rules, or whatnot. Therefore, I don't know what I'm doing or if what I attempted below is way off base.
I'm trying to figure out how to store and process the following hypothetical scenario. To simplify my problem, say that I have a type of game where a user purchases an object, where there could be 1000's of possible objects, and the objects must be purchased in a specified sequence and only in certain groups. For example, say I'm the user and I want to purchase object F. Before I can purchase object F, I must have previously purchased object A OR (B AND C). I cannot buy F and A at the same time, nor F and B,C. They must be in the sequence the rule specifies. A first, then F later. Or, B,C first, then F later. I'm not concerned right now with the span of time between purchases, or any other characteristics of the user, just that they are the correct sequence for now.
What is the best way to store this information for potentially thousands of objects that allows me to read in the rules for the object being purchased, and then check it against the user's previous purchase history?
I've attempted this, but I'm stuck at trying to implement the groupings such as A OR (B AND C). I would like to store the rules in a database where I have these tables:
Objects
(ID(int),Description(char))
ObjectPurchRules
(ObjectID(int),ReqirementObjectID(int),OperatorRule(char),Sequence(int))
But obviously as you process through the results, without the grouping, you get the wrong answer. I would like to avoid excessive string parsing if possible :). One object could have an unknown number of previous required purchases. SQL or psuedocode snippets for processing the rules would be appreciated. :)
It seems like your problem breaks down to testing whether a particular condition has been satisfied.
You will have compound conditions.
So given a table of items:
ID_Item Description
----------------------
1 A
2 B
3 C
4 F
and given a table of possible actions:
ID_Action VerbID ItemID ConditionID
----------------------------------------
1 BUY 4 1
We construct a table of conditions:
ID_Condition VerbA ObjectA_ID Boolean VerbB ObjectB_ID
---------------------------------------------------------------------
1 OWNS 1 OR MEETS_CONDITION 2
2 OWNS 2 AND OWNS 3
So OWNS means the id is a key to the Items table, and MEETS_CONDITION means that the id is a key to the Conditions table.
This isn't meant to restrict you. You can add other tables with quests or whatever, and add extra verbs to tell you where to look. Or, just put quests into your Items table when you complete them, and then interpret a completed quest as owning a particular badge. Then you can handle both items and quests with the same code.
This is a very complex problem that I'm not qualified to answer, but I've seen lots of references to. The fundamental problem is that for games, quests and items and "stats" for various objects can have non-relational dependencies. This thread may help you a lot.
You might want to pick up a couple books on the topic, and look into using LUA as a rules processor.
Personally I would do this in code, not in SQL. Each item should be its own class implementing an interface (i.e. IItem). IItem would have a method called OkToPurchase that would determine if it is OK to purchase that item. To do that, it would use one or more of a collection of rules (i.e. HasPreviouslyPurchased(x), CurrentlyOwns(x), etc.) that you can build.
The nice thing is that it is easy to extend this approach with new rules without breaking all the existing logic.
Here's some pseudocode:
bool OkToPurchase()
{
if( HasPreviouslyPurchased('x') && !CurrentlyOwns('y') )
return true;
else
return false;
}
bool HasPreviouslyPurchased( item )
{
return purchases.contains( item )
}
bool CurrentlyOwns( item )
{
return user.Items.contains( item )
}