Skip to content

Missing converter from java.util.Map to org.neo4j.driver.Value. #2576

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Bhavinpanchal20 opened this issue Aug 2, 2022 · 14 comments
Closed
Assignees
Labels
type: enhancement A general enhancement

Comments

@Bhavinpanchal20
Copy link

The below query works fine in SDN 5, But in SDN 6 they throw error.

UNWIND {0} AS row
MATCH (student:Student{guid:row.stuGuid}), (college:College{guid:row.collegeGuid})
CREATE (student)<-[:STUDENT_OF]-(college)
RETURN student.guid
public List addOwnerOfActvities(List<Map<String,String>> data);

Can anyone tell me How I resolve that issue?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 2, 2022
@michael-simons
Copy link
Collaborator

Please tell us the error thrown.

@michael-simons michael-simons added blocked: awaiting feedback and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 2, 2022
@Bhavinpanchal20
Copy link
Author

Sorry, My mistake. My problem is, that the above query does not throw any error but also they don't create a relationship and also do not return any value.

@michael-simons
Copy link
Collaborator

SDN does a lot of logging. If you set org.springframework.data.neo4j.cypher to trace, we can see the query and the parameters to it being logged.

The query here is correct, and depending on the parameters, it should create a relation.
However, SDN 6 is conceptionally different from SDN5 and it won't map arbitrary things back to you.

@Bhavinpanchal20
Copy link
Author

i got this type error.
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.util.HashMap] to type [org.neo4j.driver.Value]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jConversionService.lambda$writeValue$3(DefaultNeo4jConversionService.java:117)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:550)
at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:517)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:523)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jConversionService.writeValueImpl(DefaultNeo4jConversionService.java:143)
at org.springframework.data.neo4j.core.mapping.DefaultNeo4jConversionService.writeValue(DefaultNeo4jConversionService.java:126)
at org.springframework.data.neo4j.repository.query.Neo4jQuerySupport.convertParameter(Neo4jQuerySupport.java:204)
at org.springframework.data.neo4j.repository.query.Neo4jQuerySupport.convertParameter(Neo4jQuerySupport.java:154)
at org.springframework.data.neo4j.repository.query.StringBasedNeo4jQuery.lambda$bindParameters$8(StringBasedNeo4jQuery.java:221)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.data.neo4j.repository.query.StringBasedNeo4jQuery.bindParameters(StringBasedNeo4jQuery.java:216)
at org.springframework.data.neo4j.repository.query.StringBasedNeo4jQuery.prepareQuery(StringBasedNeo4jQuery.java:183)
at org.springframework.data.neo4j.repository.query.AbstractNeo4jQuery.execute(AbstractNeo4jQuery.java:90)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:159)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:138)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at com.sun.proxy.$Proxy166.addOwnerOfActvities(Unknown Source)

@michael-simons
Copy link
Collaborator

So you do get an error? I am confused.

@Bhavinpanchal20
Copy link
Author

Bhavinpanchal20 commented Aug 2, 2022

I apologize for this, but I got this type of error.

@Bhavinpanchal20
Copy link
Author

Just tagging @michael-simons and @meistermeier as you would be more familiar.
Please suggest to me if the above query is having any defect. Thanks Team.

@michael-simons
Copy link
Collaborator

michael-simons commented Aug 4, 2022 via email

@Bhavinpanchal20
Copy link
Author

Bhavinpanchal20 commented Aug 4, 2022

Okay, Let me try to explain a bit.
First, I take

List<Map<String,String>> list = new ArrayList<>();
Map<String,String> map = new HashMap<>():
map.put("stuGuid",23232)
map.put("collegeGuid",87833)
list.add(map)

Now, This list passes to the below query.

The Query is :

@Query("""
	UNWIND {0} AS row
	MATCH (student:Student{guid:row.stuGuid}), (college:College{guid:row.collegeGuid})
	CREATE (student)<-[:STUDENT_OF]-(college) RETURN student.guid"""
)
List<String> addStudentToCollege(List<Map<String, String>> list);

Model:

@Node
class Student{
   private String guid;
   @Relationship(type = "STUDENT_OF", direction = Direction.OUTGOING)
    private College college;
}

@Node
class College{
 private String guid;
}

Here in this scenario, I get an Error that I already mention above.
Regards,
Bhavin Panchal

@michael-simons michael-simons changed the title UNWIND query does not take List of maps Missing converter from java.util.Map to org.neo4j.driver.Value. Aug 4, 2022
@michael-simons
Copy link
Collaborator

Thanks, @Bhavinpanchal20

This will be fixed and is an enhancement.

In the meantime you can use the following workaround.

import java.util.List;

import org.neo4j.driver.Value;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;

public interface CollegeRepository extends Neo4jRepository<College, String> {

	@Query("""
		UNWIND $0 AS row
		MATCH (student:Student{guid:row.stuGuid})
		MATCH (college:College{guid:row.collegeGuid})
		CREATE (student)<-[:STUDENT_OF]-(college) RETURN student.guid"""
	)
	List<String> addStudentToCollegeWorkaround(List<Value> list);
}

Note that I rewrote the query to use modern parameters ($whathever, the {} syntax is no longer supported in recent Neo4j databases).

The parameter is now of type List<org.neo4j.driver.Value>, call it like this

@Test
void listOfMapsShouldBeUsableAsArgumentsWithWorkaround(@Autowired Neo4jTemplate template,  @Autowired CollegeRepository collegeRepository) {

	var student = template.save(new Student("S1"));
	var college = template.save(new College("C1"));

	var pair = Map.of("stuGuid", student.getGuid(), "collegeGuid", college.getGuid());
	var listOfPairs = List.of(Values.value(pair));

	var uuids = collegeRepository.addStudentToCollegeWorkaround(listOfPairs);
	assertThat(uuids).containsExactly(student.getGuid());
}

Thanks again for reporting. One final advise, if you allow: Please use 3 consecutive tickmarks ` before and after a code snippet to format it proper. This really helps us a lot. I edited one of your answers to demonstrate.

@Bhavinpanchal20
Copy link
Author

@michael-simons Thank you so much for giving me an example, we really appreciate that. But In your example you pass only one map but what about if I have a List of maps then how do I pass that dataset in the Value object?

Suppose I have this type of dataSet,
List<Map<String,String>> list = new ArrayList<>();
Map<String,String> map1 = new HashMap<>():
map1.put("stuGuid",23232)
map1.put("collegeGuid",87833)
list.add(map1)

Map<String,String> map2 = new HashMap<>():
map2.put("stuGuid",86743)
map2.put("collegeGuid",90874)
list.add(map2)

Now how i pass the list in List of Value?
List listModel = Collections.singletonList(Values.value(map));
how do I add map2 in Values.value?

@michael-simons
Copy link
Collaborator

That would be

@Test
@Tag("GH-2576")
void listOfMapsShouldBeUsableAsArgumentsWithWorkaround(@Autowired Neo4jTemplate template,
		@Autowired CollegeRepository collegeRepository) {

	Student student = template.save(new Student("S1"));
	College college = template.save(new College("C1"));

	Student student2 = template.save(new Student("S2"));
	College college2 = template.save(new College("C2"));

	Map<String, String> pair = new HashMap<>();
	pair.put("stuGuid", student.getGuid());
	pair.put("collegeGuid", college.getGuid());


	Map<String, String> pair2 = new HashMap<>();
	pair2.put("stuGuid", student2.getGuid());
	pair2.put("collegeGuid", college2.getGuid());

	List<Value> listOfPairs = Arrays.asList(Values.value(pair), Values.value(pair2));

	List<String> uuids = collegeRepository.addStudentToCollegeWorkaround(listOfPairs);
	assertThat(uuids).containsExactlyInAnyOrder(student.getGuid(), student2.getGuid());
}

@Bhavinpanchal20
Copy link
Author

@michael-simons Thank you so much for giving the example. Now we resolve that issue. Currently, we try to upgrade SDN 6 also much appreciate for you build SDN 6 from Scratch. Thanks again for your quick support :)

@michael-simons
Copy link
Collaborator

Thanks a lot, @Bhavinpanchal20 for your kind feedback, much appreciated.

Let us know in case you run into more issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants