neo4j rest api cypher似乎返回节点的笛卡尔积

时间:2014-10-16 21:50:08

标签: neo4j cypher

我使用以下数据创建了一个简单的图表:

CREATE (england:Country {Name:"England",Id:1})
CREATE CONSTRAINT ON (c:Country) ASSERT c.ID IS UNIQUE

CREATE (john:King {Name:"John",Id:1})
CREATE (henry3:King {Name:"Henry III",Id:2})
CREATE (edward1:King {Name:"Edward I",Id:3})
CREATE CONSTRAINT ON (k:King) ASSERT k.ID IS UNIQUE
MATCH (country:Country),(king:King) WHERE country.Id = 1 AND king.Id = 1 CREATE (country)<-[r:KING_OF]-(king)
MATCH (country:Country),(king:King) WHERE country.Id = 1 AND king.Id = 2 CREATE (country)<-[r:KING_OF]-(king)
MATCH (country:Country),(king:King) WHERE country.Id = 1 AND king.Id = 3 CREATE (country)<-[r:KING_OF]-(king)

CREATE (cornwall:County {Name:"Cornwall",Id:1})
CREATE (devon:County {Name:"Devon",Id:2})
CREATE (somerset:County {Name:"Somerset",Id:3})
CREATE CONSTRAINT ON (c:County) ASSERT c.ID IS UNIQUE
MATCH (country:Country),(county:County) WHERE country.Id = 1 AND county.Id = 1 CREATE (country)<-[r:COUNTY_IN]-(county)
MATCH (country:Country),(county:County) WHERE country.Id = 1 AND county.Id = 2 CREATE (country)<-[r:COUNTY_IN]-(county)
MATCH (country:Country),(county:County) WHERE country.Id = 1 AND county.Id = 3 CREATE (country)<-[r:COUNTY_IN]-(county)

CREATE (bristol:City {Name:"Bristol",Id:1})
CREATE (london:City {Name:"London",Id:2})
CREATE (york:City {Name:"York",Id:3})
CREATE CONSTRAINT ON (c:City) ASSERT c.ID IS UNIQUE
MATCH (country:Country),(city:City) WHERE country.Id = 1 AND city.Id = 1 CREATE (country)<-[r:CITY_IN]-(city)
MATCH (country:Country),(city:City) WHERE country.Id = 1 AND city.Id = 2 CREATE (country)<-[r:CITY_IN]-(city)
MATCH (country:Country),(city:City) WHERE country.Id = 1 AND city.Id = 3 CREATE (country)<-[r:CITY_IN]-(city)

(请注意,我使用'thiscomputer.mydomain.com'作为'localhost'的别名,这太可笑地禁止我使用了... ...

如果我转到http://thiscomputer.mydomain.com:7474/browser/并执行密码

MATCH cities = (city:City)-[]->(c:Country {Id:1}), counties = (county:County)-[]->(c:Country {Id:1}), kings = (king:King)-[]->(c:Country {Id:1})  RETURN cities, counties, kings

...我得到一个围绕英格兰国家的漂亮图表。没有节点重复。

如果我启动REST客户端并执行以下操作:

网址:http://thiscomputer.mydomain.com:7474/db/data/transaction/commit 动词:POST 体:

{
  "statements" : [{
"statement": "MATCH cities = (city:City)-[]->(c:Country {Id:1}), counties = (county:County)-[]->(c:Country {Id:1}), kings = (king:King)-[]->(c:Country {Id:1})  RETURN cities, counties, kings",
"resultDataContents" : [ "graph" ]
}]
}

(请注意,密码查询是相同的)

我最终得到一组太大而无法粘贴的结果。

基本上,我似乎得到了结果的笛卡尔积。由于有3个国王,3个县和3个城市,有27个结果。

这是一个相当简单的图表。在我工作的域中,我想要的图形将包含聚合根(在此示例中为英格兰),以及许多不同类型的关联节点。如果REST API返回了笛卡尔积,那么我最终可能得到数千个结果。

所以我的问题是:为什么REST API会返回所有返回节点的笛卡尔积?我的密码是不正确的,还是我错误地使用了REST API?

如果我能得到这样的结果(伪JSON)会更简单:

{
  Country:{
    Name: "England",
    Id: 1,
    Cities:[
      ...etc
    ],
    Counties:[
      ...etc
    ],
    Kings:[
      ...etc
    ]
  }
}

甚至可能是这样:

{
  data:{
    nodes:[
      {
        Name:"England",
        Id: 1,
        uniqueIdInResults:1
      },
      ...etc
    ],
    relationships:[
      uniqueIdInResults1: 1,
      uniqueIdInResults2: 2,
      type: "KING_OF"
    ] 
  }
}

简而言之,我认为像这样对结果中的数据进行非规范化会很快导致响应过大。有没有办法构造cypher或调用REST API来减少重复的结果?

1 个答案:

答案 0 :(得分:3)

您在浏览器中运行的查询也绝对会返回笛卡尔积 - 它只是不会出现这种情况,因为视觉结果只会显示一次节点。

在浏览器中运行以下命令。你会很快看到你所得到的所有重叠。

MATCH cities = (city:City)-[]->(c:Country {Id:1}), 
      counties = (county:County)-[]->(c:Country {Id:1}), 
      kings = (king:King)-[]->(c:Country {Id:1})  
RETURN EXTRACT(x IN NODES(cities) | x.Name),
       EXTRACT(x IN NODES(counties) |x.Name), 
       EXTRACT(x IN NODES(kings) | x.Name)

正如所料,我得到了27行的笛卡尔积。