Skip to content

Commit c6314ad

Browse files
GH-2444 - Use either property CONTAINS string or item IN collectionProperty.
This fixes #2444.
1 parent cea6ba5 commit c6314ad

File tree

3 files changed

+151
-2
lines changed

3 files changed

+151
-2
lines changed

src/main/java/org/springframework/data/neo4j/repository/query/CypherQueryCreator.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,7 @@ private Condition createImpl(Part part, Iterator<Object> actualParameters) {
338338
case BETWEEN:
339339
return betweenCondition(path, actualParameters, ignoreCase);
340340
case CONTAINING:
341-
return toCypherProperty(path, ignoreCase)
342-
.contains(toCypherParameter(nextRequiredParameter(actualParameters, property), ignoreCase));
341+
return containingCondition(path, property, actualParameters, ignoreCase);
343342
case ENDING_WITH:
344343
return toCypherProperty(path, ignoreCase)
345344
.endsWith(toCypherParameter(nextRequiredParameter(actualParameters, property), ignoreCase));
@@ -397,6 +396,17 @@ private Condition createImpl(Part part, Iterator<Object> actualParameters) {
397396
}
398397
}
399398

399+
private Condition containingCondition(PersistentPropertyPath<Neo4jPersistentProperty> path,
400+
Neo4jPersistentProperty property, Iterator<Object> actualParameters, boolean ignoreCase) {
401+
402+
Expression cypherProperty = toCypherProperty(path, ignoreCase);
403+
if (property.isCollectionLike()) {
404+
return toCypherParameter(nextRequiredParameter(actualParameters, property), ignoreCase).in(cypherProperty);
405+
}
406+
return cypherProperty
407+
.contains(toCypherParameter(nextRequiredParameter(actualParameters, property), ignoreCase));
408+
}
409+
400410
/**
401411
* Checks whether to ignore the case for some operations. {@link PartTreeNeo4jQuery} will already have
402412
* validated which properties can be made case insensitive given a certain keyword.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright 2011-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.integration.imperative
17+
18+
import org.junit.jupiter.api.Assertions.assertNotNull
19+
import org.junit.jupiter.api.BeforeAll
20+
import org.junit.jupiter.api.Test
21+
import org.neo4j.driver.Driver
22+
import org.springframework.beans.factory.annotation.Autowired
23+
import org.springframework.context.annotation.Bean
24+
import org.springframework.context.annotation.Configuration
25+
import org.springframework.data.neo4j.config.AbstractNeo4jConfig
26+
import org.springframework.data.neo4j.core.DatabaseSelectionProvider
27+
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager
28+
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager
29+
import org.springframework.data.neo4j.integration.shared.common.TestNode
30+
import org.springframework.data.neo4j.repository.Neo4jRepository
31+
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories
32+
import org.springframework.data.neo4j.repository.query.Query
33+
import org.springframework.data.neo4j.test.BookmarkCapture
34+
import org.springframework.data.neo4j.test.Neo4jExtension
35+
import org.springframework.data.neo4j.test.Neo4jIntegrationTest
36+
import org.springframework.transaction.PlatformTransactionManager
37+
import org.springframework.transaction.annotation.EnableTransactionManagement
38+
39+
@Neo4jIntegrationTest
40+
class Neo4jListContainsTest {
41+
42+
companion object {
43+
@JvmStatic
44+
private lateinit var neo4jConnectionSupport: Neo4jExtension.Neo4jConnectionSupport
45+
46+
@BeforeAll
47+
@JvmStatic
48+
fun prepareDatabase(@Autowired driver: Driver, @Autowired bookmarkCapture: BookmarkCapture) {
49+
driver.session().use { session ->
50+
session.run("MATCH (n) DETACH DELETE n").consume()
51+
session.run("CREATE (testNode:GH2444{id: 1, items: ['item 1', 'item 2', 'item 3'], description: 'desc 1'})").consume();
52+
bookmarkCapture.seedWith(session.lastBookmark())
53+
}
54+
}
55+
}
56+
57+
@Autowired
58+
private lateinit var testNodeRepository: TestNodeRepository
59+
60+
@Test
61+
fun `Should find test node by items containing`() {
62+
val testNode = testNodeRepository.findByItemsContains("item 2")
63+
assertNotNull(testNode)
64+
}
65+
66+
@Test
67+
fun `Should find test node by using explicit query`() {
68+
val testNode = testNodeRepository.findByItemsContainsWithExplicitQuery("item 2")
69+
assertNotNull(testNode)
70+
}
71+
72+
@Test
73+
fun `Should find test node by description in`() {
74+
val testNode = testNodeRepository.findByDescriptionIn(listOf("desc 1", "desc 2", "desc 3"))
75+
assertNotNull(testNode)
76+
}
77+
78+
@Configuration
79+
@EnableTransactionManagement
80+
@EnableNeo4jRepositories
81+
open class MyConfig : AbstractNeo4jConfig() {
82+
@Bean
83+
override fun driver(): Driver {
84+
return neo4jConnectionSupport.driver
85+
}
86+
87+
@Bean
88+
open fun bookmarkCapture(): BookmarkCapture {
89+
return BookmarkCapture()
90+
}
91+
92+
@Bean
93+
override fun transactionManager(driver: Driver, databaseNameProvider: DatabaseSelectionProvider): PlatformTransactionManager {
94+
val bookmarkCapture = bookmarkCapture()
95+
return Neo4jTransactionManager(driver, databaseNameProvider, Neo4jBookmarkManager.create(bookmarkCapture))
96+
}
97+
}
98+
}
99+
100+
interface TestNodeRepository : Neo4jRepository<TestNode, Long> {
101+
102+
fun findByItemsContains(item: String): TestNode?
103+
104+
@Query("""MATCH (t:GH2444) WHERE ${"$"}item IN t.items RETURN t""")
105+
fun findByItemsContainsWithExplicitQuery(item: String): TestNode?
106+
107+
fun findByDescriptionIn(descriptions: List<String>): TestNode?
108+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2011-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.integration.shared.common
17+
18+
import org.springframework.data.neo4j.core.schema.GeneratedValue
19+
import org.springframework.data.neo4j.core.schema.Id
20+
import org.springframework.data.neo4j.core.schema.Node
21+
22+
@Node("GH2444")
23+
data class TestNode(
24+
25+
@Id
26+
@GeneratedValue
27+
val id: Long,
28+
29+
val description: String,
30+
val items: List<String>
31+
)

0 commit comments

Comments
 (0)