2015-06-10 3 views
0

У меня есть запрос на шифр (ниже). Это работает, но мне было интересно, есть ли более элегантный способ написать это.количество подключенных узлов к определенным узлам в пути

На основании данного стартового узла, запрос пытается:

  1. Найдите следующий шаблон/мотив: (inputko)-->(:cpd)-->(ko2:ko)-->(:cpd)-->(ko3:ko).

  2. Foreach мотивы/шаблоны найдены, найти подключенные узлы с метками contigs, для следующих узлов в схеме: [inputko, ko2, ko3].

  3. Краткое описание трех узлов и их подключенных коннигов, т.е. имя свойства .ko из 3 узлов и количество подключенных :contig узлов в каждом из найденных мотивов (inputko)-->(:cpd)-->(ko2:ko)-->(:cpd)-->(ko3:ko).

    +--------------------------------------------------------------------------+ 
    | KO1   | KO1count | KO2   | KO2count | KO3   | KO3count | 
    +--------------------------------------------------------------------------+ 
    | "ko:K00001" | 102  | "ko:K14029" | 512  | "ko:K03736" | 15  | 
    | "ko:K00001" | 102  | "ko:K00128" | 792  | "ko:K12972" | 7  | 
    | "ko:K00001" | 102  | "ko:K00128" | 396  | "ko:K01624" | 265  | 
    | "ko:K00001" | 102  | "ko:K03735" | 448  | "ko:K00138" | 33  | 
    | "ko:K00001" | 102  | "ko:K14029" | 512  | "ko:K15228" | 24  | 
    +--------------------------------------------------------------------------+ 
    

Я озадачен синтаксис для работы на каждом матче. Из документации оговорка foreach не похоже на то, что мне нужно. Любые идеи парней?

Предложение FOREACH используется для обновления данных в коллекции, будь то компонентов пути или результата агрегирования.

Коллекции и пути являются ключевыми понятиями в Cypher. Чтобы использовать их для обновления данных , вы можете использовать конструкцию FOREACH. Он позволяет делать команды для элементов в коллекции - путь или набор , созданный путем агрегации.

START 
    inputko=node:koid('ko:\"ko:K00001\"') 
MATCH 
    (inputko)--(c1:contigs) 
WITH 
    count(c1) as KO1count, inputko 
MATCH 
    (inputko)-->(:cpd)-->(ko2:ko)-->(:cpd)-->(ko3:ko) 
WITH 
    inputko.ko as KO1, 
    KO1count, 
    ko2, 
    ko3 
MATCH 
    (ko2)--(c2:contigs) 
WITH 
    KO1, 
    KO1count, 
    ko2.ko as KO2, 
    count(c2) as KO2count, 
    ko3 
MATCH 
    (ko3)--(c3:contigs) 
RETURN 
    KO1, 
    KO1count, 
    KO2, 
    KO2count, 
    ko3.ko  AS KO3, 
    count(c3) AS KO3count 
LIMIT 
    5; 

понял, что я должен поместить в отличие для count(distinct cX), чтобы получить точный подсчет. Не знаю почему.

ответ

1

Я не знаю, как элегантный это, но я думаю, что это даст вам некоторое представление о том, как вы могли бы расширить запрос для n kò узлов в пути и по-прежнему возвращать данные, как вы положили его ниже. Он также должен продемонстрировать силу объединения директивы и коллекций with.

// match the ko/cpd node paths starting with K00001 
match p=(ko1:ko {name:'K00001' })-->(:cpd)-->(ko2:ko)-->(:cpd)-->(ko3:ko) 

// remove the cpd nodes from each path and name the collection row 
with collect([n in nodes(p) where labels(n)[0] = 'ko' | n]) as row 

// create a range for the number of rows and number of ko nodes per row 
with row 
, range(0, length(row)-1, 1) as idx 
, range(0, 2, 1) as idx2 

// iterate over each row and node in the order it was collected 
unwind idx as i 
unwind idx2 as j 
with i, j, row[i][j] as ko_n 

// find all of the contigs nodes atttached to each ko node 
match ko_n--(:contigs) 

// group the ko node data together in a collection preserving the order and the count 
with i, [j, ko_n.name, count(*)] as ko_set 
order by i, ko_set[0] 

// re-collect the ko node sets as ko rows 
with i, collect(ko_set) as ko_row 
order by i 

//return the original paths in the ko node order with the counts 
return reduce(ko_str = "", ko in ko_row | 
    case 
    when ko_str = "" then ko_str + ko[1] + ", " + ko[2] 
    else ko_str + ", " + ko[1] + ", " + ko[2] 
    end) as `KO-Contigs Counts` 

foreach директива шифром строго для мутирует данных. Например, вы можете использовать один запрос для сбора счетчиков contigs на узел ko.

Это немного запутанный, и вы никогда не будете обновлять количество contigs на ko узле, как это, но он иллюстрирует использование foreach в шифре.

match (ko:ko)-->(:contigs) 
with ko,count(*) as ct 
with collect(ko) as ko_nodes, collect(ct) as ko_counts 
with ko_nodes, ko_counts, range(0,length(ko_nodes)-1, 1) as idx 
foreach (i in idx | 
     set (ko_nodes[i]).num_contigs = ko_counts[i] ) 

Более простой способ для выполнения поставленной задачи обновления на каждом узле ko будет делать что-то вроде этого ...

match (ko:ko)-->(:contigs) 
with ko, count(*) as ct 
set ko.num_contigs = ct 

Если вы должны были нести дэ число контигов на каждом узле ко-то вы могли бы выполнить запрос, как это, чтобы возвратить число

// match all the paths starting with K00001 
match p=(ko1:ko {name:'K00001' })-->(:cpd)-->(ko2:ko)-->(:cpd)-->(ko3:ko) 
// build a csv line per path 
return reduce(ko_str = "", ko in nodes(p) | ko_str + 
    // using just the ko nodes in the path 
    // exclude the cpd nodes 
    case 
     when labels(ko)[0] = "ko" then ko.name + ", " + toString(ko.num_contigs) + ", " 
     else "" 
    end 
) as `KO-Contigs Counts` 
+0

согласен с вами по этому вопросу. «Если вы должны были переносить количество контрсов на каждом узле ko, тогда вы можете выполнить такой запрос, чтобы вернуть номер kos« возможно, все обновления узлов KO для хранения этой информации! это сделает запрос слишком быстрым – altimit

Смежные вопросы