Cayley : How to put the limit/depth to show the graph hierarchy in cayley? - cayley

I need help to limit the nodes to show the graph hierarchy in cayley. Like in OrientDB we have a depth function to restrict the hierarchy to any level up to same level down.
Example: I have a below hierarchy:
A DependsOn B
B RunsOn C
C DependsOn D
D ConnectedTo E
Now, for the above example I have written a below query to show the graph hierarchy.
var path = g.M().Both();
g.V("B").FollowRecursive(path).ForEach( function(v) {
g.V(v.id).OutPredicates().ForEach( function(r){
g.V(v.id).Out().ForEach(function(t){
var node = {
source: v.id,
relation : r.id
target: t.id
}
g.Emit(node)
})
}
})
So, when I am passing B to the query it will return me the complete hierarchy but I want only A ,B & C nodes to show for 1 level hierarchy from B, same thing for 2 level hierarchy I want to show A,B,C & D as it should show 2 level up and 2 level down from the B node.

You can limit the depth by passing the max depth as second parameter to the FollowRecursive function:
g.V("B").FollowRecursive(path,2 )
Please not that you start a new path in the foreach which does not know about the max depth in the outer function.
A more detailed discussing about this use-case can be found at the 'cross-post' on the official Cayley forum:
https://discourse.cayley.io/t/cayley-0-7-0-depth-function-issue/1066

Related

How to get ordered results from couchbase

I have in my bucket a document containing a list of ID (childList).
I would like to query over this list and keep the result ordered like in my JSON. My query is like (using java SDK) :
String query = new StringBuilder().append("SELECT B.name, META(B).id as id ")
.append("FROM" + bucket.name() + "A ")
.append("USE KEYS $id ")
.append("JOIN" + bucket.name() + "B ON KEYS ARRAY i FOR i IN A.childList end;").toString();
This query will return rows that I will transform into my domain object and create a list like this :
n1qlQueryResult.allRows().forEach(n1qlQueryRow -> (add to return list ) ...);
The problem is the output order is important.
Any ideas?
Thank you.
here is a rough idea of a solution without N1QL, provided you always start from a single A document:
List<JsonDocument> listOfBs = bucket
.async()
.get(idOfA)
.flatMap(doc -> Observable.from(doc.content().getArray("childList")))
.concatMapEager(id -> bucket.async().get(id))
.toList()
.toBlocking().first();
You might want another map before the toList to extract the name and id, or to perform your domain object transformation even maybe...
The steps are:
use the async API
get the A document
extract the list of children and stream these ids
asynchronously fetch each child document and stream them but keeping them in original order
collect all into a List<JsonDocument>
block until the list is ready and return that List.

Dynamic, General Indexing in R

Is there a way to index across many lists, data frames, etc., in R? That is to say, generally? For example, you could retrieve a list of the second element of the second element of lists a & b via c(a[[2]][[2]],b[[2]][[2]]), but how can you do this without writing the names of each list and the respective indexing brackets?
Input:
l1 <- as.list(c(1,2,3,4,5))
l2 <- as.list(c(6,7,8,9,10))
a <- list(l1,l2)
l4 <- as.list(c(1,2,3,4,5))
l5 <- as.list(c(6,7,8,9,10))
b <- list(l4,l5)
Desired output:
[1] 7 7
I know that you could create a list of only upper nested lists - assuming the same naming convention - with this:
nol <- objects()
nol <- grep("^[a-z]$", nol, value=TRUE)
I just don't know how to apply across this list.
You can do this via vapply as follows:
vapply(mget(nol), function(x) x[[2]][[2]], FUN.VALUE = double(1), USE.NAMES = FALSE)
The idea here is that mget gives you a list of your objects. you could also create it by list(a,b). And the anonymous function function(x) x[[2]][[2]] returns your values.

neo4j query performance takes a lot of time

I am facing a query performance issue. Do let me know if I am making any mistake here.
I have created around 1700 (Router nodes) and around 4000 (interface nodes) where interfaces are connected to their respective routers using relation (has_interface).
Now I want to create a link between these interfaces. A link will be a relation. Every interface has an IfIPAddress prop associated with it.
When I try to create a link using this query, it runs for a very long time, takes a lot of CPU and then do not create any link.
Here is my query
MATCH (I:Interface), (I2:Interface)
FOREACH(p in FILTER(z in {props} WHERE z.OrigIPAddress = I.IfIPAddress and z.TermIPAddress = I2.IfIPAddress) |
MERGE (:Interface {IfIPAddress:p.OrigIPAddress})-[r:link]->(:Interface {IfIPAddress:p.TermIPAddress})
ON CREATE SET r = p
ON MATCH SET r = p)
Here is what I provide to neo4j using json and curl
{
"params" : {
"props" : [
{
"AreaId" : "",
"OrigIPAddress" : "172.16.42.9",
"OrigNodeID" : "192.168.1.221",
"TermIPAddress" : "172.16.42.10",
"TermNodeID" : "10.229.140.28",
"eEntityStatus" : "1",
"iTotalBW" : "0"
}
]
},
"query" : "MATCH (I:Interface), (I2:Interface) FOREACH(p in FILTER(z in {props} WHERE z.OrigIPAddress = I.IfIPAddress and z.TermIPAddress = I2.IfIPAddress) | MERGE (:Interface {IfIPAddress:p.OrigIPAddress})-[r:link]->(:Interface {IfIPAddress:p.TermIPAddress}) ON CREATE SET r = p ON MATCH SET r = p)"
}
This is what I am doing in the query
First in the FILTER I am removing all those links whose OrigIPAddress or TermIPAddress are not present in the neo4j
After that for every props, I am creating a link between the interfaces.
I am using neo4j 2.1. When neo4j server was running with default configurations it gave error as "OutOFMemory Exception"
I increased the heap size of the server and it is taking a lot of time
Let me know if anything I have missed.
Do let me know if you need logs.
First of all: your query creates a cross product, i.e. it pulls in 8M pairs.
Try something like this first, and report back if it does not work.
FOREACH(p in {props} |
MERGE (I:Interface{IfIPAddress:p.OrigIPAddress})
MERGE (I2:Interface {IfIPAddress:p.TermIPAddress})
MERGE (I)-[r:link]->(I2)
SET r = p
)
You should not set all the properties on r that's just a waste. Only set the properties there that you really need.
Instead of:
SET r = p
do something like this:
SET r.uptime = p.uptime
How many elements do you have in {props} ?
What is your current server configuration? In terms of heap, mmio etc?
Best to share path/to/neo4j/data/graph.db/messages.log for diagnostics.

Parsing numerical data using Prolog?

I am new to prolog and am considering using it for a small data analysis application. Here is what I am seeking to accomplish:
I have a CSV file with some data of the following from:
a,b,c
d,e,f
g,h,i
...
The data is purely numerical and I need to do the following: 1st, I need to group rows according to the following scheme:
So what's going on above?
I start at the 1st row, which has value 'a' in column one. Then, I keep going down the rows until I hit a row whose value in column one differs from 'a' by a certain amount, 'z'. The process is then repeated, and many "groups" are formed after the process is complete.
For each of these groups, I want to find the mean of columns two and three (as an example, for the 1st group in the picture above, the mean of column two would be: (b+e+h)/3).
I am pretty sure this can be done in prolog. However, I have 50,000+ rows of data and since prolog is declarative, I am not sure how efficient prolog would be at accomplishing the above task?
Is it feasible to work out a prolog program to accomplish the above task, so that efficiency of the program is not significantly lower than a procedural analog?
this snippet could be a starting point for your task
:- [library(dcg/basics)].
rownum(Z, AveList) :- phrase_from_file(row_scan(Z, [], [], AveList), 'numbers.txt').
row_scan(Z, Group, AveSoFar, AveList) -->
number(A),",",number(B),",",number(C),"\n",
{ row_match(Z, A,B,C, Group,AveSoFar, Group1,AveUpdated) },
row_scan(Z, Group1, AveUpdated, AveList).
row_scan(_Z, _Group, AveList, AveList) --> "\n";[].
% row_match(Z, A,B,C, Group,Ave, Group1,Ave1)
row_match(_, A,B,C, [],Ave, [(A,B,C)],Ave).
row_match(Z, A,B,C, [H|T],Ave, Group1,Ave1) :-
H = (F,_,_),
( A - F =:= Z
-> aggregate_all(agg(count,sum(C2),sum(C3)),
member((_,C2,C3), [(A,B,C), H|T]), agg(Count,T2,T3)),
A2 is T2/Count, A3 is T3/Count,
Group1 = [], Ave1 = [(A2,A3)|Ave]
; Group1 = [H,(A,B,C)|T], Ave1 = Ave
).
with this input
1,2,3
4,5,6
7,8,9
10,2,3
40,5,6
70,8,9
16,0,0
yields
?- rownum(6,L).
L = [ (3.75, 4.5), (5, 6)]

Play 2.0 Complex join query how to parse (Anorm )

I am writing website using play 2.0 framework. And I have a problem when parsing results.
This request to mysql db gets all the links(can be several per episode) added to the database per episode together with all the information about episode and anime.
def lastReleasedLink(limit:Long=5):List[(((Episode,Anime),Link),Genre)] = {
DB.withConnection { implicit c =>
SQL(
"""
select * from yas_episodes as a
inner join anime as b on a.ep_anime_id=b.id
left outer join yas_links as c on a.ep_id=c.ep_id
LEFT JOIN yas_animes_genres AS d ON a.ep_anime_id = d.ag_anime_id
INNER JOIN yas_genres AS e ON e.g_id = d.ag_genre_id
where c.ep_id IS NOT NULL group by c.ep_id order by c.date desc limit {limit}
""").on('limit ->limit)as(Episode.simple~Anime.simple~Link.simple~Genre.simple map{
case episode~anime~link~genre => episode -> anime -> link -> Genre
} *)
}
}
The return value is type of List[(((Episode,Anime),Link),Genre)]
but how can I form output to the list of
let say List[episode,anime,Seq[links]] or List[episode,anime,Seq[Genres],Seq[links]] don't know where to put genres.
You can imagine that when you have two links per one episode information from table anime and yas_episodes will be copied for every row. So I need somehow stack them together(group) by episode record. Then it will be possible to iterate list and access to all objects.
As you can see, in the request there is many-to-many relation of anime with genres.
I have no idea how can I put all together to one list to be able to access it in view. Should Genre be part of Anime model?
It seems that the preferred way to achieve this is using the Scala collection API, see this post by Guillaume Bort.
In your case, I think you could do something like
lastReleasedLink groupBy { case (((e, a), l), g) => (e, a) }
to group by (Episode, Anime). Generally speaking, those manipulations are probably a little easier if you change your function to return a List[(Episode, Anime, Link, Genre)], i.e.
case episode~anime~link~genre => (episode, anime, link, genre)
then you could achieve the same with this code:
lastReleasedLink groupBy ((_._1, _._2))