Friends of Friends in Sparksee

53 views
Skip to first unread message

oj

unread,
Feb 23, 2015, 1:35:54 AM2/23/15
to spar...@googlegroups.com
Hello!

I want to query Sparksee to get the friends of friends of a given person(P). From the friends of friends, I want to remove people who are already friends with P. 

These are the steps that I have taken:

1) Get the friends of P
Objects friends = g.neighbors(nodeP, friendType, EdgesDirection.Outgoing);


2) Get the fof of U
Objects fof= g.explode(friends, friendType, EdgesDirection.Outgoing);

Here I use the explode since I need to perform an aggregate on the friends of friends, hence I cannot use the unique object identifiers returned by g.neighbors.

3) Now I need to remove friends from fof

it = fof.iterator();
while (it.hasNext())
{
   
long x=it.next();
   
EdgeData d=g.getEdgeData(x);
    l
=d.getHead();
   
if(friends.exists(l))
        fof
.remove(x);
}

This throws an exception: 
An ObjectsIterator can't be used after it's Objects parent is closed or modified

What seems to be the problem here?

Also, ideally, it would be better to iterate the 'friends' instead of 'fof' and remove any objects, if it exists in fof. But I'm not sure how I can do this.

These are the two methods I can think of, please suggest  alternate methods (if any) that will be more efficient.

Thanks!






c3po.ac

unread,
Feb 23, 2015, 6:00:25 AM2/23/15
to spar...@googlegroups.com
Hi,

You can't remove items from an "Objects" while you are iterating it. Removing items invalidates the iterator.

The difference between Neighbors and Explode is that Neighbors returns a set of nodes while Explode returns returns a set of edges.
If you are only interested in the nodes and not the edges, you can use Neighbors.

You can get P's friends as you do:

Objects friends = g.neighbors(nodeP, friendType, EdgesDirection.Outgoing);

Then you can get all the friends of P's friends using neighbors:
Objects fof = g.neighbors(friends, friendType, EdgesDirection.Outgoing);

What you have here are 2 sets of objects (nodes) identifiers. So, you can use set operations:
Objects fof_but_not_f = Objects.combineDifference(fof, friends);

If you don't need "fof" anymore, you could have used it's "difference" method instead of the static "combineDifference" (that returns a new Objects).

You may want to check if the starting node P exists in
fof_but_not_f also and maybe remove it.

Best regards.

El dilluns, 23 febrer de 2015 7:35:54 UTC+1, oj va escriure:

oj

unread,
Feb 23, 2015, 6:47:52 AM2/23/15
to spar...@googlegroups.com
Hi,

Thanks for the reply. 

But the problem is that I have to perform explode in the second step. The reason is later (after removing the direct friends) I need to iterate the edges, get the head of each edge and count the number of times the node exists; something like a group by and a count. 

If I do the second step using neighbors, each node will occur only once resulting in a count of 1 for each node, which is meaningless.

Is there any other method I can get fof_but_not_f  preserving the duplicates in fof ?

c3po.ac

unread,
Feb 23, 2015, 9:13:23 AM2/23/15
to spar...@googlegroups.com
Hi,

Sorry, then your algorithm is ok. Just don't remove the edges.
You can use the same loop to calculate the aggregates using any external structure (a hashmap maybe) to keep the count for each node instead of keeping the valid edges or you could create a new Objects and add the valid edges there.

Another alternative, assuming that there's only one friend edge between two nodes (at least for each direction) and that the only reason to get the edge is to count the friends,  could be something like this:
 
 
       Objects friends = g.neighbors(nodeP, friendType, EdgesDirection.Outgoing);

         
ObjectsIterator it = friends.iterator();
         
while (it.hasNext())
         
{
             
long x=it.next();
             
Objects foaf = g.neighbors(x, friendType, EdgesDirection.Outgoing);
             
ObjectsIterator foaf_it = foaf.iterator();
             
while (foaf_it.hasNext())
             
{
                 
long y = foaf_it.next();
                 
if (!firends.exists(y))
                 
{
                     
// Increment the counter of Y using a map or any other structure to keep the counter for each node visited
                 
}
             
}
             foaf_it
.close();
             foaf
.close();
         
}
         it
.close();
         friends
.close();


That's a lot of neighbors calls, but if you have materialitzed the neighbors, using this neighbors calls should be very efficient. So it could be faster.

Another option could be to add this line after the inner neighbors:
foaf.difference(friends);
And then you don't have to check if "y" exists in the friends objects anymore.
But using the difference in this case may be slower than using exists.

Best regards.

El dilluns, 23 febrer de 2015 12:47:52 UTC+1, oj va escriure:
Reply all
Reply to author
Forward
0 new messages