Neo4j 存储库无法将 Collect() 映射到集合类型的字段

问题描述 投票:0回答:1

我正在使用 Neo4j 构建一个论坛。在我的论坛中,有些帖子属于某些类别,并且可能包含多个标签。当我从数据库中获取线程时,我希望结果以以下形式返回:

{
id,
title,
creationDateTime,
likeCount,
postCount,
viewCount,
tags: []
}

为了实现这一目标,我在查询中使用了 COLLECT{} 表达式。以下是我的疑问:

@Query("CREATE (accountType:AccountType {id: randomUUID(), name: $name, authorities: $authorities}) RETURN accountType")
    public AccountType createAccountType(String name, List<AccountTypeEnum> authorities);

@Query("MERGE (accountType:AccountType {name: 'NORMAL_USER'}) " +
            "CREATE (newAccount:ForumAccount:NotificationTrigger {id: randomUUID(), userName: $userName, password: $password, email: $email, joinDate: date(), type: 'account'}) " +
            "MERGE (newAccount)-[:BELONGS_TO_ACCOUNT_TYPE]->(accountType) " +
            "RETURN newAccount")
    public ForumAccount createNewAccount(String userName, String password, String email);

@Query("CREATE (category:Category {id: randomUUID(), categoryName: $categoryName}) RETURN category.id AS id, category.categoryName AS categoryName")
    public Category createCategory(String categoryName);

@Query("CREATE (tag:Tag {id: randomUUID(), tagName: $tagName}) RETURN tag")
    public Tag createNewTag(String tagName);

@Query("MATCH (user:ForumAccount {id: $accountId}) " +
            "MATCH (category:Category {id: $categoryId}) " +
            "MERGE (category)-[:CONTAINS_THREAD]->(thread: Thread {id: randomUUID(), title: $title, creationDateTime: localdatetime(), toxicStatus: $toxicStatus, resolveStatus: false}) " +
            "MERGE (user)-[:CREATES]->(thread) " +
            "MERGE (thread)-[:CREATED_BY]->(user) " +
            "WITH thread, COALESCE($tags, []) AS tags " +
            "FOREACH (tagData IN tags | " +
            "   MERGE (tag:Tag {id: tagData.__id__, tagName: tagData.__properties__.tagName}) " +
            "   MERGE (thread)-[:CONTAINS_TAGS]->(tag) " +
            "   MERGE (tag)-[:BELONGS_TO]->(thread)) " +
            "RETURN thread")
    public Thread addNewThread(UUID accountId, String title, String toxicStatus, Set<Tag> tags, UUID categoryId);

 @Query("MATCH (author:ForumAccount {id: $accountId})-[:CREATES]->(thread:Thread {toxicStatus: 'NOT_TOXIC'}) " +
            "RETURN thread.id AS id, thread.title AS title, thread.resolveStatus as resolveStatus, thread.creationDateTime AS creationDateTime, 0 AS likeCount, 0 AS postCount, 0 AS viewCount, " +
            "COLLECT {OPTIONAL MATCH (thread)-[:CONTAINS_TAGS]->(tag:Tag) RETURN tag.tagName} AS tags " +
            "ORDER BY thread.creationDateTime " +
            "SKIP $offset LIMIT $limit"
    )
    public List<StandardThreadResponseDTO> getThreadsByAccountId(UUID accountId, int offset, int limit);

以下是我的StandardThreadResponseDTO

package com.gymhub.gymhub.dto.ResponseDTO.ThreadResponseDTO;

import com.gymhub.gymhub.domain.Tag;
import com.gymhub.gymhub.dto.ResponseDTO.TagResponseDTO;
import lombok.*;
import org.springframework.data.neo4j.core.schema.Node;

import java.time.LocalDateTime;
import java.util.*;

@Getter
@Setter
@NoArgsConstructor
public class StandardThreadResponseDTO {
    private UUID id;
    private String title;
    private LocalDateTime creationDateTime;
    private boolean resolveStatus;

    @Setter
    private int likeCount;
    @Setter
    private int viewCount;
    @Setter
    private int postCount;

    private Set<String> tags = new HashSet<>();

    public StandardThreadResponseDTO(UUID id, String title, LocalDateTime creationDateTime, boolean resolveStatus, Set<String> tags) {
        this.id = id;
        this.title = title;
        this.creationDateTime = creationDateTime;
        this.resolveStatus = resolveStatus;
        this.tags = tags;
    }

    @Override
    public String toString() {
        return "StandardThreadResponseDTO{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", creationDateTime=" + creationDateTime +
                ", resolveStatus=" + resolveStatus +
                ", tags=" + tags +
                '}';
    }
}

以下是我的函数调用

 @Test
    public void testingThreadCreation(){
        //Generating Category
        Category category = threadRepository.createCategory(ThreadCategoryEnum.ADVICE.name());
        System.out.println(category.getId());
        //Generating Account Type
        List<AccountTypeEnum> types = new ArrayList<>();
        types.add(AccountTypeEnum.NORMAL_USER);
        AccountType accountType= forumAccountRepository.createAccountType( "NORMAL_USER", types);

        //Generating Account
        ForumAccount newAccount = forumAccountRepository.createNewAccount("TrungLuong0806", passwordEncoder.encode("TestAccount123"), "[email protected]");
        System.out.println(newAccount.getId());

        //Generate Tags
        Tag tag_1 = tagRepository.createNewTag("LateralRaise");
        Tag tag_2 = tagRepository.createNewTag("ShoulderWorkout");


        Set<Tag> tags = new HashSet<>();
        tags.add(tag_1);
        tags.add(tag_2);



        //Generate Threads
        //Thread thread = threadRepository.addNewThread(newAccount.getId(), "Is Lateral Raise an optimal exercises for shoulders", ToxicStatusEnum.NOT_TOXIC.name(), tags);
        Thread thread = threadRepository.addNewThread(newAccount.getId(), "Is Lateral Raise an optimal exercises for shoulders", ToxicStatusEnum.NOT_TOXIC.name(), tags, category.getId());
        System.out.println("Thread ID: " + thread.getId());
        System.out.println(threadRepository.findTagsInThread(thread.getId()));
        //Fetch all threads created by the user
        System.out.println(threadRepository.getThreadsByAccountId(newAccount.getId(), 0, 5));


    }

我已经确认函数调用导致创建具有正确关系的新标签。但是,调用 threadRepository.getThreadsByAccountId(newAccount.getId(), 0, 5) 会返回带有空标签集的正确线程参数,考虑到所有标签均已正确创建,这种情况不应该发生:

[StandardThreadResponseDTO{id=2e108544-52e9-4c2d-bd9b-62bd88bd1be9, title='Is Lateral Raise an optimal exercises for shoulders', creationDateTime=2024-10-09T01:54:17.731, resolveStatus=false, tags=[]}]

你能告诉我为什么标签集合是空的吗?我已确保为 DTO 使用匹配的字段名称

neo4j spring-data-neo4j
1个回答
0
投票

提取“collect”中的嵌套语句,即使使用子查询也是“call {....}”

@Query("MATCH (author:ForumAccount {id: $accountId})-[:CREATES]->(thread:Thread {toxicStatus: 'NOT_TOXIC'}) " +
   "OPTIONAL MATCH (thread)-[:CONTAINS_TAGS]->(tag:Tag) " +
   "WITH thread, COLLECT(tag.tagName) AS tn " +
   "RETURN thread.id AS id, thread.title AS title, thread.resolveStatus AS resolveStatus, " +
   "thread.creationDateTime AS creationDateTime, 0 AS likeCount, 0 AS postCount, 0 AS viewCount, " +
   "tn " +
   "ORDER BY thread.creationDateTime " +
   "SKIP $offset LIMIT $limit")

使用子查询

@Query("MATCH (author:ForumAccount {id: $accountId})-[:CREATES]->(thread:Thread {toxicStatus: 'NOT_TOXIC'}) " +
   "CALL { " +
   "    WITH thread " +
   "    OPTIONAL MATCH (thread)-[:CONTAINS_TAGS]->(tag:Tag) " +
   "    RETURN COLLECT(tag.tagName) AS tags " +
   "} AS tagCollection " +
   "RETURN thread.id AS id, thread.title AS title, thread.resolveStatus AS resolveStatus, " +
   "thread.creationDateTime AS creationDateTime, 0 AS likeCount, 0 AS postCount, 0 AS viewCount, " +
   "tagCollection.tags AS tags " +
   "ORDER BY thread.creationDateTime " +
   "SKIP $offset LIMIT $limit")
© www.soinside.com 2019 - 2024. All rights reserved.