I'm newbie to Neo4j/GraphDB and have created following simple graph
node[1]user1 which is 'friend' with node[2]user2 and node[3]user3
and all 3 above user have 'post' nodes connected to them as well..
question is how to get user1's connected friend and their post as well?
following query returns friends of user1 and his post only...
START user1=node(2) MATCH user1-->all_node RETURN all_node
Depending on the relationship types you have chosen, something like this should work:
START user1=node(2)
MATCH user1-[:FRIEND]->friend-[:POST]->post
RETURN friend,post
Related
We are trying to implement Customer oriented details in Graphdb, were with a single query we can fetch the details of a customer such as his address,phone,email etc. We have build it using had address, has email edges..
g.addV('member').property('id','CU10611972').property('CustomerId', 'CU10611972').property('TIN', 'xxxx').property('EntityType', 'Person').property('pk', 'pk')
g.addV('email').property('id','CU10611972E').property('pk', 'pk')
g.addV('primary').property('id','CU10611972EP').property('EmailPreference','Primary').property('EmailType', 'Home').property('EmailAddress', 'SNEHA#GMAIL.COM').property('pk', 'pk')
g.V('CU10611972').addE('has Email').to(g.V('CU10611972E'))
g.V('CU10611972E').addE('has Primary Email').to(g.V('CU10611972EP')
This is how we have build email relation to the customer.. Similarly we have relations with Address and Phone. So right now we are using this command to fetch the json related to this customer for email,
g.V('CU10611972').out('has Email').out('has Primary Email')
And for complete Customer details we are using union for each Vertex, Phone,Emaiul and address..
Could you please suggest if there is an efficient way to query this detail?
This comes down really to two things.
General graph data modelling
Things the graph DB you are using does and does not support.
With Gremlin there are a few ways to model this data for a single vertex.
If the database supports it, have a list of names like ['home','mobile'] and use metaproperties to attach a phone number to each.
A lot of the Gremlin implementations I am aware of have chosen not to support meta properties. In these cases you have a couple of options.
(a) Have a property for 'Home' and another for 'Mobile'. If either is not known you could either not create that property or give it a value such as "unknown"
(b) Use prefixed strings such as ["Home:123456789","Mobile:123456789] and store them in a set or list (multi properties) and access them in Gremlin using the startingWith predicate. Such as g.V(id).properties('phone').hasValue(startingWith('Mobile')).value()
I have a data model like this:
Person node
Email node
OWNS relationship
LISTS relationship
KNOWS relationship
each Person can OWN one Email and LISTS multiple Emails (like a contact list, 200 contacts is assumed per Person).
The query I am trying to perform is finding all the Persons that OWN an Email that a Contact LISTS and create a KNOWS relationship between them.
MATCH (n:Person {uid:'123'}) -[r1:LISTS]-> (m:Email) <-[r2:OWNS]- (l:Person)
CREATE UNIQUE (n)-[:KNOWS]->[l]
The counts of my current database is as follows:
Number of Person nodes: 10948
Number of Email nodes: 1951481
Number of OWNS rels: 21882
Number of LISTS rels: 4376340 (Each Person has 200 unique LISTS rels)
Now my problem is that running the said query on this current database takes something between 4.3 to 4.8 seconds which is unacceptable for my need. I wanted to know if this is normal timing considering my data model or am I doing something wrong with the query (or even model).
Any help would be much appreciated. Also if this is normal for Neo4j please feel free to suggest other graph databases that can handle this kind of model better.
Thank you very much in advance
UPDATE:
My query is: profile match (n: {uid: '4692'}) -[:LISTS]-> (:Email) <-[:OWNS]- (l) create unique (n)-[r:KNOWS]->(l)
The PROFILE command on my query returns this:
Cypher version: CYPHER 2.2, planner: RULE. 3919222 total db hits in 2713 ms.
Yes, 4.5 seconds to match one person from index along with its <=100 listed email addresses and merging a relationship from user to the single owner of each email, is slow.
The first thing is to make sure you have an index for uid property on nodes with :Person label. Check your indices with SCHEMA command and if missing create such an index with CREATE INDEX ON :Person(uid).
Secondly, CREATE UNIQUE may or may not do the work fine, but you will want to use MERGE instead. CREATE UNIQUE is deprecated and though they are sometimes equivalent, the operation you want performed should be expressed with MERGE.
Thirdly, to find out why the query is slow you can profile it:
PROFILE
MATCH (n:Person {uid:'123'})-[:LISTS]->(m:Email)<-[:OWNS]-(l:Person)
MERGE (n)-[:KNOWS]->[l]
See 1, 2 for details. You may also want to profile your query while forcing the use of one or other of the cost and rule based query planners to compare their plans.
CYPHER planner=cost
PROFILE
MATCH (n:Person {uid:'123'})-[:LISTS]->(m:Email)<-[:OWNS]-(l:Person)
MERGE (n)-[:KNOWS]->[l]
With these you can hopefully find and correct the problem, or update your question with the information to help others help you find it.
I have streams with relations with categories and users, but those relations are optional relations. So streams should not always be related to a category or user, it may just related to a category or multiple categories or users. My question is I want to join two optional queries which handle all those cases. Example below, behaves like this, it works if both category and user relations exists for node, but does not work if node has only a user relation in example.Any ideas?
MATCH (stream:Stream {id: "xyz123"})
MATCH (stream)-[:CONTAINS]->(categories)-[:CHILD_OF*0..50]->(subcats)<-[:PHOTO_OF]-(photo), (stream)<-[:PARTICIPANT_OF]-(users)<-[:OWNER]-(photo)
WHERE photo.is_private=false
return collect(photo.id) as photo_ids
What i need is intersection of two matchings if both user and category relations exists. if only category or user relations exists bring only the result of that relation
Does this work for you?
MATCH (stream:Stream { id: "xyz123" })
OPTIONAL MATCH (stream)-[:CONTAINS]->(categories)-[:CHILD_OF*0..50]->(subcats)<-[:PHOTO_OF]-(photo)
WHERE photo.is_private=false
WITH stream, COLLECT(photo) AS p1
OPTIONAL MATCH (stream)<-[:PARTICIPANT_OF]-(users)<-[:OWNER]-(photo)
WHERE photo.is_private=false
WITH stream, p1 + COLLECT(photo) AS pCombined
UNWIND pCombined AS photo
RETURN COLLECT(DISTINCT photo.id) AS photo_ids
Here is a console that shows this query working.
I'm working for a big professional social network and we are starting to check if OrientDB meets our requirements in terms of Social Graph. For now on, we have managed to deploy a cluster of 10 nodes, setup backups and restore and populate all of our data from MongoDB to OrientDB with no major issues.
Our data model is :
vertices :
Profile
Company
Job
Publication
...
edges :
Followed : one profile can follow another profile or a company
Applied : one profile can apply to a job
Posted : one profile can post some publication on the network
...
What I want to know is :
How to get all people connected to one given profile at depth 1 or 2. I've tried something like SELECT out('Followed').out('Followed') as friend FROM 14:4 where 14:4 is a Profile object. Unfortunately, it gives me Profiles as well as Companies since a Profile can "Followed" a Company. How can I filter to get Profiles only ? I've tried SELECT out('Followed').out('Followed') as friend FROM 14:4 where #class = 'Profile' but it does not work :( Should I have multiple edge classes (FollowedProfile and FollowedCompany) to ease queries ?
When a Profile creates an account using another Social Network (Facebook, Google, ...) we are storing his existing contacts and match them with our database so we can say "Profile A is connected to Profile B thanks to Facebook". How should I represent that in OrientDB ? An attribute on the edge or a dedicated edge class ?
Last one is : how can I get the shortest path between two Profiles ?
Thanks a lot.
1) You can try with
SELECT FROM (SELECT expand(out('Followed').out('Followed')) as friend FROM 14:4) Where #class='Profile'
2) I think An attribute (thanks) on the edge is better
3) You can use shortestPath function (http://www.orientechnologies.com/docs/last/orientdb.wiki/SQL-Functions.html) :
Example:
select shortestPath(#8:32, #8:10, 'BOTH')
I am trying to access FeedItems and topics(tags) associated to each FeedItem in a chatter Group. I am not able to figure out the relationship between FeedItems and Topics tagged with FeedItem.
I am able to get all the FeedItems in a chatter Group using the following soql Query:
SELECT c.id, c.CreatedDate, c.InsertedBy.Name FROM CollaborationGroupFeed c
WHERE c.Parent.Name = 'Chatter_Group_name'
Similarly I can get all the Topics using following soql Query:
Select Id, Name from Topic
But i need to get each FeedItem with Topics tagged with it (if any).
Following is the image to better understand it.
I need to get the topics mentioned in the black rectangle.
Can anyone help me to get the Required output? Let me know if Other information is required regarding this.
You need to query the TopicAssignment object like this:
List<TopicAssignment> myFeedItemFeedAssignments = [
SELECT
Id,
NetworkId,
TopicId,
Topic.Name,
EntityId,
EntityKeyPrefix
FROM
TopicAssignment
WHERE
EntityId IN :feedItemId
Each TopicAssignment record has a Name property
P.S. You might get more responses by posting on salesforce.stackexchange.com