带过滤器的

时间:2016-12-25 12:11:16

标签: neo4j cypher

我正在尝试获得一个密码,它可以为我提供路径和可用的源位置。以下是我的图表设置

create (t1:Trip{id:"red"}), (t2:Trip{id:"blue"}), (a:City{id:"A"}), (b:City{id:"B"}), (c:City{id:"C"}), (d:City{id:"D"}) 
create (t1)-[:stop_at]->(a),(t1)-[:stop_at]->(b),(t1)-[:stop_at]->(c),(t1)-[:stop_at]->(d),(t2)-[:stop_at]->(a),(t2)-[:stop_at]->(b),(t2)-[:stop_at]->(c),(t2)-[:stop_at]->(d)
create (a)-[:red]->(b),(b)-[:red]->(c),(c)-[:red]->(d) create (a)-[:blue]->(b),(b)-[:blue]->(c),(c)-[:blue]->(d) 
create (b)-[:red_01{seat:40}]->(c),(c)-[:red_01{seat:40}]->(d)

我有两个“旅行”,“红色”和“蓝色”。使用“Trip”id在节点(停靠点)之间创建的关系只是抽象链接。我想寻找在“A”和“D”停留的旅行,我使用以下查询返回“红色”和“蓝色”行程。

 match (t:Trip)-[:stop_at]->(c:City) where c.id = "A" or c.id = "D" return distinct t.id

然后我想获取路径,我正在使用以下查询。

 match (t:Trip)-[:stop_at]->(c:City) where c.id = "A" or c.id = "D" with distinct t.id as id
 match (source:City{id:"A"})-[rel*]->(dest:City{id:"D"}) where all(item in rel where starts with id) return rel

它返回36行,它们组合了每个可能的路径。例如:

[(A)-[:blue]->(B), (B)-[:blue]->(C), (C)-[:blue]->(D)]
[(A)-[:red]->(B), (B)-[:red]->(C), (C)-[:red]->(D)]
[(A)-[:red]->(B), (B)-[:red]->(C), (C)-[:red_01 {seat:40}]->(D)]
[(A)-[:red]->(B), (B)-[:red_01 {seat:40}]->(C), (C)-[:red]->(D)]
[(A)-[:red]->(B), (B)-[:red_01 {seat:40}]->(C), (C)-[:red_01 {seat:40}]->(D)]

我想得到的是:

[(A)-[:blue]->(B), (B)-[:blue]->(C), (C)-[:blue]->(D)]
[(A)-[:red]->(B), (B)-[:red_01 {seat:40}]->(C), (C)-[:red_01 {seat:40}]->(D)]

后缀“_01”表示两站之间的日期/时间旅行有售。对于所有“红色”旅行,我希望只获得包含最大销售额的路径。如果我们查看上面的结果,它将是第5行。“蓝色”旅行当天没有任何销售,因此我们将保留结果。

这是neo4j控制台供您参考。非常感谢你的帮助。

http://console.neo4j.org/?id=2sho3j

赖安

1 个答案:

答案 0 :(得分:0)

此查询是回答您的解决方案的一步:

match (t:Trip)-[:stop_at]->(c:City)
where c.id = "A" or c.id = "D"
with distinct t.id as id
match (source:City{id:"A"})-[rel*]->(dest:City{id:"D"})
where all(item in rel where type(item) starts with id)
return rel, extract(r in rel | type(r)) as reltypes

它返回:

╒════════════════════════════╤═════════════════════╕
│rel                         │reltypes             │
╞════════════════════════════╪═════════════════════╡
│[{}, {}, {}]                │[blue, blue, blue]   │
├────────────────────────────┼─────────────────────┤
│[{}, {seat: 40}, {}]        │[red, red_01, red]   │
├────────────────────────────┼─────────────────────┤
│[{}, {seat: 40}, {seat: 40}]│[red, red_01, red_01]│
├────────────────────────────┼─────────────────────┤
│[{}, {}, {}]                │[red, red, red]      │
├────────────────────────────┼─────────────────────┤
│[{}, {}, {seat: 40}]        │[red, red, red_01]   │
└────────────────────────────┴─────────────────────┘

但是,我认为我们应该首先改进数据模型:

  • 在关系类型中使用后缀来表示可能经常更改的内容(此处,表示是否有销售)是一个坏主意。我建议使用关系属性,例如sale: true/false,或将销售日期添加为列表(存储日期可能很棘手:使用时间戳,字符串,APOC date/time support - 最适合您的用例。
  • 您也可以考虑将路线的颜色存储为属性,例如(a)-[:ROUTE {colour: 'red'}]->(b) ROUTE应尽可能具有描述性,例如TRAINCONNECTED_BY_TRAIN}。

所以,回到你的问题(使用原始数据模型):你可以使用各种方法计算特定路径上的销售额:

reduce

match (t:Trip)-[:stop_at]->(c:City)
where c.id = "A" or c.id = "D"
with distinct t.id as id
match (source:City{id:"A"})-[rel*]->(dest:City{id:"D"})
where all(item in rel where type(item) starts with id)
return rel, extract(r in rel | type(r)) AS reltypes,
  reduce(
    noSales = 0,
    item IN rel | noSales +
      case type(item) ends with '_01'
        when true then 1
        else 0
      end) AS noSales

或更简单的宽度filterlength

match (t:Trip)-[:stop_at]->(c:City)
where c.id = "A" or c.id = "D"
with distinct t.id as id
match (source:City{id:"A"})-[rel*]->(dest:City{id:"D"})
where all(item in rel where type(item) starts with id)
return rel, extract(r in rel | type(r)) AS reltypes,
  length(filter(item in rel where type(item) ends with '_01')) AS noSales

两者都返回以下结果:

╒════════════════════════════╤═════════════════════╤═══════╕
│rel                         │reltypes             │noSales│
╞════════════════════════════╪═════════════════════╪═══════╡
│[{}, {}, {}]                │[blue, blue, blue]   │0      │
├────────────────────────────┼─────────────────────┼───────┤
│[{}, {seat: 40}, {}]        │[red, red_01, red]   │1      │
├────────────────────────────┼─────────────────────┼───────┤
│[{}, {seat: 40}, {seat: 40}]│[red, red_01, red_01]│2      │
├────────────────────────────┼─────────────────────┼───────┤
│[{}, {}, {}]                │[red, red, red]      │0      │
├────────────────────────────┼─────────────────────┼───────┤
│[{}, {}, {seat: 40}]        │[red, red, red_01]   │1      │
└────────────────────────────┴─────────────────────┴───────┘

要获得最大的销售额,您只需排序并获得最佳结果:

order by noSales desc
limit 1