Spring Data Neo4j:按LocalDate过滤不起作用 [英] Spring Data Neo4j: filter by LocalDate doesn't work

查看:116
本文介绍了Spring Data Neo4j:按LocalDate过滤不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的小型Neo4j游乐场应用程序(基于Spring Boot 2,Spring Data Neo4j和嵌入式驱动程序)是一个小型的记笔记软件.用户可以按创建日期过滤其笔记.为了更好地了解Cypher,我使用SDN的@Query(NoteRepo.findByDay(day))编写了Cypher查询.

My small Neo4j playground application (based on Spring Boot 2, Spring Data Neo4j and the embedded driver) is a small note-keeping software. The users can filter their notes by creation date. To get a better understanding of Cypher I wrote the Cypher query using SDN's @Query (NoteRepo.findByDay(day)).

但是我无法进行过滤.我对LocalDate转换为地图(控制台输出的最后一行)感到困惑.在上一个查询(NoteRepo.findBySnoozeUntil(day),使用SDN的repo查询关键字)中,一切都很好,并且day转换为ISO 8601日期.

However I can't get the filtering working. I'm confused that the LocalDate was transformed into a map (last line of the console output). In the previous query (NoteRepo.findBySnoozeUntil(day), using SDN's repo query keywords) everything was fine and the day was transformed to a ISO 8601 date.

有人可以指出它有什么问题并修复它吗?

Can somebody please point out what's wrong with it and fix it?

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 = []


repro项目:将此添加到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'
}

并添加上面的类.

推荐答案

目前,使用嵌入式驱动程序对派生的查询器(类似于List<Note> findBySnoozedUntil(LocalDate day);的查询器)的处理方式与使用@Query注释的查询器的处理方式有所不同.

At the moment the derived queriers (one like List<Note> findBySnoozedUntil(LocalDate day);) are handled differently than the ones annotated with @Query using the embedded driver.

嵌入式驱动程序当前将所有参数映射到字符串上.对于这两个,它无条件地使用Jacksons ObjectMapper的实例.

The embedded driver currently maps all parameters onto strings. To two this, it uses unconditionally an instance of Jacksons ObjectMapper.

我们需要几个步骤来解决此问题.

We need several steps to fix this.

  1. 教ObjectMapper使用合理的格式.这很容易,您已经启动了,所以请添加此启动程序compile('org.springframework.boot:spring-boot-starter-json'),它将带来许多有用的Jackson模块.如果您打算编写Web应用程序并且已经具有spring-boot-starter-webspring-boot-starter-webflux,则可以省略JSON启动器,这些模块会将其启动.

  1. Teach ObjectMapper to use a reasonable format. That's easy, you're on Boot, so please add this starter compile('org.springframework.boot:spring-boot-starter-json'), it brings a lot of useful Jackson modules. If you intend to write a web application and already have spring-boot-starter-web or spring-boot-starter-webflux, you can omit the JSON starter, those modules bring it.

注册包含的Java 8 Jackson模块与OGMs嵌入式Objectmapper并禁用将日期作为时间戳写入,即在您的App.class中:

Register the included Java 8 Jackson modules with OGMs Embedded Objectmapper and disable writing dates as timestamps, i.e. in your App.class:

final ObjectMapper ogmObjectMapper = org.neo4j.ogm.config.ObjectMapperFactory.objectMapper();
ogmObjectMapper.registerModule(new JavaTimeModule());
ogmObjectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

  1. 由于嵌入式驱动程序使用此配置将值映射为String,因此您不得不修改查询:

@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对外部数据库也可以看到相同的效果,解决方案目前是相同的.

The same effect would be seen using Bolt against an external database as well, solution is currently the same.

这篇关于Spring Data Neo4j:按LocalDate过滤不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆