SDN Neo4J Cypher 查询可能存在 Spring 数据错误
A possible Spring Data Bug with SDN Neo4J Cypher Query
下面的查询应该return账户按降序排列"followers",有限制。
它需要 2 个变量作为参数(maxCount 和 limit)。 MaxCount 指的是追随者的数量。因此,如果 maxCount 为 100,则 return 仅那些关注者少于 100 的帐户。
如果我 运行 在 Spring Data Neo4j 应用程序中进行此查询。它似乎忽略了 maxCount 约束,例如如果我将 maxCount 设置为 2 并且 account1 有 3 个关注者,account2 有 1 个关注者。它似乎不正确 return 这两个帐户应该只有 return 只有 1 个关注者的帐户 2。
查询
@Query("MATCH (a:Account)<-[:follows]-(b:Account) WITH a, COLLECT(b)
AS bs WHERE SIZE(bs) < {0} RETURN a ORDER BY SIZE(bs) DESC LIMIT {1}")
List<Account> findCappedSortedAccountByFollowers(int maxCount, int resultSize);
如果我直接将它输入 Neo4j 控制台就可以了
也许这是 Spring 数据错误?
SDN版本:4.1.3.RELEASE
OGM 嵌入式驱动程序版本:2.0.5
可用的小应用程序来演示问题here
您的代码已更新为适用于新版本。两个测试都通过了。我已经重写了您的测试和模型,使其更符合我们的文档和示例。请记住,OGM 可以通过可达性持续存在。希望这可以帮助您解决问题。我已经在此处解释了如何使用 Spring 数据编写事务类型测试:.
build.gradle
:
dependencies {
compile "ch.qos.logback:logback-classic:1.1.7"
compile "org.springframework.data:spring-data-neo4j:4.2.0.BUILD-SNAPSHOT"
compile "org.springframework:spring-test:4.3.3.RELEASE"
compile "org.neo4j:neo4j-ogm-embedded-driver:2.1.0-SNAPSHOT"
testCompile "junit:junit:4.12"
}
src/main/java
com.neo4j.relation.config
:
@Configuration
@EnableNeo4jRepositories("com.neo4j.relation.repository")
@EnableTransactionManagement
public class EmbeddedNeo4JConfig {
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory("com.neo4j.relation.model");
}
@Bean
public PlatformTransactionManager transactionManager() {
return new Neo4jTransactionManager(sessionFactory());
}
}
src/main/java
com.neo4j.relation.model
:
@NodeEntity
public class Account {
@GraphId
private Long id;
private String name;
@Relationship(type = "FOLLOWS",
direction = Relationship.OUTGOING)
private Set<Account> following = new HashSet<Account>();
@Relationship(type = "FOLLOWS",
direction = Relationship.INCOMING)
private Set<Account> followers = new HashSet<Account>();
private Account() {
}
private Account(String name) {
this.name = name;
}
public static Account newAccountInstance(String name) {
return new Account(name);
}
//Accessors
public Long getId() {
return id;
}
public Set<Account> getFollowers() {
return followers;
}
public String getName() {
return name;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Id: ").append(getId()).append(", ");
sb.append("Name: ").append(getName()).append(", ");
return sb.toString();
}
}
src/main/java
com.neo4j.relation.repository
:
public interface AccountRepository extends GraphRepository<Account> {
@Query("MATCH (a:Account)<-[:FOLLOWS]-(b:Account) WITH a, COLLECT(b) AS bs ORDER BY SIZE(bs) DESC RETURN a LIMIT {0}")
List<Account> findSortedAccountByFollowers(int maxSize);
@Query("MATCH (a:Account)<-[:FOLLOWS]-(b:Account) WITH a, COLLECT(b) AS bs WHERE SIZE(bs) <= {0} RETURN a ORDER BY SIZE(bs) DESC LIMIT {1}")
List<Account> findCappedSortedAccountByFollowers(int maxCount, int resultSize);
}
src/test/resources
logback.xml
:
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
</encoder>
</appender>
<logger name="org.neo4j.ogm" level="debug" />
<logger name="org.springframework" level="warn" />
<logger name="org.springframework.data.neo4j" level="debug" />
<root level="debug">
<appender-ref ref="console" />
</root>
</configuration>
src/test/resources
com.neo4j.test
:
@ContextConfiguration(classes = {EmbeddedNeo4JConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
public class AccountTester {
@Autowired
AccountRepository accountRepository;
@Test
public void testFindSortedAccountByFollowers() {
Account account = Account.newAccountInstance("James Martin");
Account account2 = Account.newAccountInstance("Steve Owen");
Account account3 = Account.newAccountInstance("Bill Gates");
Account account4 = Account.newAccountInstance("Steve Jobs");
account.getFollowers().add(account2);
accountRepository.save(account);
accountRepository.save(account3);
accountRepository.save(account4);
assertNotNull(account.getId());
final Iterable<Account> all = accountRepository.findAll();
assertEquals(4, IteratorUtils.size(all.iterator()));
List<Account> accounts = accountRepository.findSortedAccountByFollowers(10);
int size = accounts.size();
assertEquals(1, size);
assertEquals(account, accounts.get(0));
}
@Test
public void testCappedSortAccountByFollowerCount() {
Account account = Account.newAccountInstance("Steve Martin");
Account account2 = Account.newAccountInstance("Steve Owen");
Account account3 = Account.newAccountInstance("Bill Gates");
Account account4 = Account.newAccountInstance("Steve Jobs");
account.getFollowers().add(account2);
account.getFollowers().add(account3);
account.getFollowers().add(account4);
account4.getFollowers().add(account3);
accountRepository.save(account);
List<Account> accounts = accountRepository.findCappedSortedAccountByFollowers(2, 10);
int size = accounts.size();
assertEquals(1, size);
assertEquals(account4, accounts.get(0));
}
}
下面的查询应该return账户按降序排列"followers",有限制。
它需要 2 个变量作为参数(maxCount 和 limit)。 MaxCount 指的是追随者的数量。因此,如果 maxCount 为 100,则 return 仅那些关注者少于 100 的帐户。
如果我 运行 在 Spring Data Neo4j 应用程序中进行此查询。它似乎忽略了 maxCount 约束,例如如果我将 maxCount 设置为 2 并且 account1 有 3 个关注者,account2 有 1 个关注者。它似乎不正确 return 这两个帐户应该只有 return 只有 1 个关注者的帐户 2。
查询
@Query("MATCH (a:Account)<-[:follows]-(b:Account) WITH a, COLLECT(b)
AS bs WHERE SIZE(bs) < {0} RETURN a ORDER BY SIZE(bs) DESC LIMIT {1}")
List<Account> findCappedSortedAccountByFollowers(int maxCount, int resultSize);
如果我直接将它输入 Neo4j 控制台就可以了
也许这是 Spring 数据错误?
SDN版本:4.1.3.RELEASE
OGM 嵌入式驱动程序版本:2.0.5
可用的小应用程序来演示问题here
您的代码已更新为适用于新版本。两个测试都通过了。我已经重写了您的测试和模型,使其更符合我们的文档和示例。请记住,OGM 可以通过可达性持续存在。希望这可以帮助您解决问题。我已经在此处解释了如何使用 Spring 数据编写事务类型测试:
build.gradle
:
dependencies {
compile "ch.qos.logback:logback-classic:1.1.7"
compile "org.springframework.data:spring-data-neo4j:4.2.0.BUILD-SNAPSHOT"
compile "org.springframework:spring-test:4.3.3.RELEASE"
compile "org.neo4j:neo4j-ogm-embedded-driver:2.1.0-SNAPSHOT"
testCompile "junit:junit:4.12"
}
src/main/java
com.neo4j.relation.config
:
@Configuration
@EnableNeo4jRepositories("com.neo4j.relation.repository")
@EnableTransactionManagement
public class EmbeddedNeo4JConfig {
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory("com.neo4j.relation.model");
}
@Bean
public PlatformTransactionManager transactionManager() {
return new Neo4jTransactionManager(sessionFactory());
}
}
src/main/java
com.neo4j.relation.model
:
@NodeEntity
public class Account {
@GraphId
private Long id;
private String name;
@Relationship(type = "FOLLOWS",
direction = Relationship.OUTGOING)
private Set<Account> following = new HashSet<Account>();
@Relationship(type = "FOLLOWS",
direction = Relationship.INCOMING)
private Set<Account> followers = new HashSet<Account>();
private Account() {
}
private Account(String name) {
this.name = name;
}
public static Account newAccountInstance(String name) {
return new Account(name);
}
//Accessors
public Long getId() {
return id;
}
public Set<Account> getFollowers() {
return followers;
}
public String getName() {
return name;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Id: ").append(getId()).append(", ");
sb.append("Name: ").append(getName()).append(", ");
return sb.toString();
}
}
src/main/java
com.neo4j.relation.repository
:
public interface AccountRepository extends GraphRepository<Account> {
@Query("MATCH (a:Account)<-[:FOLLOWS]-(b:Account) WITH a, COLLECT(b) AS bs ORDER BY SIZE(bs) DESC RETURN a LIMIT {0}")
List<Account> findSortedAccountByFollowers(int maxSize);
@Query("MATCH (a:Account)<-[:FOLLOWS]-(b:Account) WITH a, COLLECT(b) AS bs WHERE SIZE(bs) <= {0} RETURN a ORDER BY SIZE(bs) DESC LIMIT {1}")
List<Account> findCappedSortedAccountByFollowers(int maxCount, int resultSize);
}
src/test/resources
logback.xml
:
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
</encoder>
</appender>
<logger name="org.neo4j.ogm" level="debug" />
<logger name="org.springframework" level="warn" />
<logger name="org.springframework.data.neo4j" level="debug" />
<root level="debug">
<appender-ref ref="console" />
</root>
</configuration>
src/test/resources
com.neo4j.test
:
@ContextConfiguration(classes = {EmbeddedNeo4JConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
public class AccountTester {
@Autowired
AccountRepository accountRepository;
@Test
public void testFindSortedAccountByFollowers() {
Account account = Account.newAccountInstance("James Martin");
Account account2 = Account.newAccountInstance("Steve Owen");
Account account3 = Account.newAccountInstance("Bill Gates");
Account account4 = Account.newAccountInstance("Steve Jobs");
account.getFollowers().add(account2);
accountRepository.save(account);
accountRepository.save(account3);
accountRepository.save(account4);
assertNotNull(account.getId());
final Iterable<Account> all = accountRepository.findAll();
assertEquals(4, IteratorUtils.size(all.iterator()));
List<Account> accounts = accountRepository.findSortedAccountByFollowers(10);
int size = accounts.size();
assertEquals(1, size);
assertEquals(account, accounts.get(0));
}
@Test
public void testCappedSortAccountByFollowerCount() {
Account account = Account.newAccountInstance("Steve Martin");
Account account2 = Account.newAccountInstance("Steve Owen");
Account account3 = Account.newAccountInstance("Bill Gates");
Account account4 = Account.newAccountInstance("Steve Jobs");
account.getFollowers().add(account2);
account.getFollowers().add(account3);
account.getFollowers().add(account4);
account4.getFollowers().add(account3);
accountRepository.save(account);
List<Account> accounts = accountRepository.findCappedSortedAccountByFollowers(2, 10);
int size = accounts.size();
assertEquals(1, size);
assertEquals(account4, accounts.get(0));
}
}