我的小型Neo4j运动场应用程序(基于Spring Boot 2,Spring Data Neo4j和嵌入式驱动程序)是一个小型的记笔记软件。用户可以按创建日期过滤其笔记。为了更好地了解Cypher,我使用SDN的@Query
(NoteRepo.findByDay(day)
)编写了Cypher查询。
但是我无法进行过滤。我对LocalDate转换为地图(控制台输出的最后一行)感到困惑。在上一个查询(NoteRepo.findBySnoozeUntil(day)
中,使用SDN的repo查询关键字),一切都很好,并且day
转换为ISO 8601日期。
有人可以指出它的问题并进行修复吗?
Note.java
@NodeEntity
class Note {
@Id
@GeneratedValue
private Long id;
private String content;
private LocalDateTime created;
private LocalDate snoozedUntil;
// constructors, getters, setters, ... omitted
}
NoteRepo.java
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import java.time.LocalDate;
import java.util.List;
interface NoteRepo extends Neo4jRepository<Note, Long> {
// FIXME find all notes created on a specific day
// currently returns an empty list
@Query("MATCH (n: Note) WHERE date(datetime(n.created)) = {0} RETURN n")
List<Note> findByDay(LocalDate day);
List<Note> findBySnoozeUntil(LocalDate day);
}
App.java
package com.example.neo4jquerywithlocaldate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.time.LocalDate;
import java.time.LocalDateTime;
@SpringBootApplication
public class App {
public static void main(String[] args) {
var ctx = SpringApplication.run(App.class, args);
var repo = ctx.getBean(NoteRepo.class);
var tomorrow = LocalDate.now().plusDays(1);
repo.save(new Note("learn neo4j", LocalDateTime.now(), tomorrow));
var notesForTomorrow = repo.findBySnoozeUntil(tomorrow);
System.out.println("notes snoozed until tomorrow = " + notesForTomorrow);
var todaysNotes = repo.findByDay(LocalDate.now());
System.out.println("today's notes = " + todaysNotes);
}
}
Spring Boot应用程序的控制台输出(被截断为Neo4j查询和System.out.println)
UNWIND {rows} as row CREATE (n:`Note`) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, {type} as type with params {type=node, rows=[{nodeRef=-1, props={snoozeUntil=2018-09-21, created=2018-09-20T19:38:54.732260, content=learn neo4j}}]}
MATCH (n:`Note`) WHERE n.`snoozeUntil` = { `snoozeUntil_0` } WITH n RETURN n, ID(n) with params {snoozeUntil_0=2018-09-21}
< notes for tomorrow = [Note{id=0, content='learn neo4j', created=2018-09-20T19:38:54.732260}]
MATCH (n: Note) WHERE date(datetime(n.created)) = {0} RETURN n with params {0={year=2018, month=SEPTEMBER, monthValue=9, dayOfMonth=20, chronology={id=ISO, calendarType=iso8601}, dayOfWeek=THURSDAY, era=CE, dayOfYear=263, leapYear=false}}
< today's notes = []
复制项目:Spring Initializr Project
将此添加到build.gradle
:
ext['neo4j-ogm.version'] = '3.1.3'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'
runtimeOnly 'org.neo4j:neo4j:3.4.7'
runtimeOnly 'org.neo4j:neo4j-ogm-embedded-driver:3.1.3'
}
并添加上面的类。
答案 0 :(得分:1)
目前,使用嵌入式驱动程序处理派生查询器(类似于List<Note> findBySnoozedUntil(LocalDate day);
的查询器与用@Query
注释的查询器)的处理方式不同。
嵌入式驱动程序当前将所有参数映射到字符串上。对于这两个,它无条件地使用Jacksons ObjectMapper的实例。
我们需要几个步骤来解决此问题。
教ObjectMapper使用合理的格式。这很容易,您已经启动了,因此请添加此启动程序compile('org.springframework.boot:spring-boot-starter-json')
,它将带来许多有用的Jackson模块。如果您打算编写一个Web应用程序并且已经拥有spring-boot-starter-web
或spring-boot-starter-webflux
,则可以省略JSON启动程序,这些模块将其引入。
在OGM的嵌入式Objectmapper中注册随附的Java 8 Jackson modules,并禁用写入日期作为时间戳,即在您的App.class中:
final ObjectMapper ogmObjectMapper = org.neo4j.ogm.config.ObjectMapperFactory.objectMapper();
ogmObjectMapper.registerModule(new JavaTimeModule());
ogmObjectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
@Query("MATCH (n: Note) WHERE date(datetime(n.created)) = date({0}) RETURN n")
List<Note> findByDay(LocalDate day);
相关的输出现在是
2018-09-24 10:50:53.313 INFO 2860 --- [ main] o.n.o.d.e.request.EmbeddedRequest : Request: MATCH (n:`Note`) WHERE n.`snoozedUntil` = { `snoozedUntil_0` } WITH n RETURN n, ID(n) with params {snoozedUntil_0=2018-09-25}
notes snoozed until tomorrow = [com.example.demo.Note@2420e962]
2018-09-24 10:50:53.522 INFO 2860 --- [ main] o.n.o.d.e.request.EmbeddedRequest : Request: MATCH (n: Note) WHERE date(datetime(n.created)) = date({0}) RETURN n with params {0=2018-09-24}
today's notes = [com.example.demo.Note@363d3958]
编辑:使用Bolt对外部数据库也可以看到相同的效果,解决方案目前是相同的。