You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data Neo4j查询主节点及子节点时出现重复数据问题

问题描述

我有Console和Computer两个根节点,各自包含多层子节点。使用Spring Data Neo4j Repository查询全量数据时,返回的Console对象虽包含子节点,但存在重复数据。我需要返回无重复的主节点及其完整子节点树。

我编写了一段在Neo4j控制台可正常运行的自定义Cypher查询,但在Spring环境中无法生效,代码如下:

@Query("MATCH path=(root:categories)-[:HAS_SUBCATEGORY*0..]->(sub:categories) " +
        "WHERE NOT ()-[:HAS_SUBCATEGORY]->(root) " +
        "WITH root, collect(sub) as subcategories " +
        "RETURN root, subcategories")
List<CategoryEntity> findCategoriesWithSubcategories();

期望的返回JSON格式:

{
    "id": "29514e97-42fb-4c42-bfc7-6689e48f1c5f",
    "name": "Console",
    "description": "Video games",
    "subCategories": [
        {
            "id": "a054c37c-908d-46e5-ae80-b171dc2271a4",
            "name": "Playstation",
            "description": "video games",
            "subCategories": [
                {
                    "id": "081d526b-2251-467e-86e4-e37638d04de6",
                    "name": "Playstation5",
                    "description": null,
                    "subCategories": [],
                    "primary": false
                },
                {
                    "id": "16e8df4e-06ea-4e52-816a-839ac7bb7201",
                    "name": "Playstation4",
                    "description": null,
                    "subCategories": [],
                    "primary": false
                }
            ],
            "primary": false
        },
        {
            "id": "35f5484e-a700-403d-862a-4c20ead1eb12",
            "name": "Xbox",
            "description": "video games",
            "subCategories": [
                {
                    "id": "956b42e9-fe6a-4b0e-a701-eaba86832f7a",
                    "name": "XboxSeries",
                    "description": null,
                    "subCategories": [],
                    "primary": false
                },
                {
                    "id": "f2369cd8-6e3f-473f-94c9-d89cf0cb0cdb",
                    "name": "XboxOne",
                    "description": null,
                    "subCategories": [],
                    "primary": false
                }
            ]
        }
    ],
    "primary": true
}

对应的实体类代码:

@Node("categories")
public class CategoryEntity {

    @Id
    private String id;

    @Property(name = "name")
    private String name;

    @Property(name = "description")
    private String description;

    @Property(name = "is_primary")
    private boolean isPrimary;

    @Relationship(type = "HAS_SUBCATEGORY", direction = Relationship.Direction.OUTGOING)
    private Set<CategoryEntity> subCategories;

    @Property(name = "created_at")
    private Instant createdAt;

    @Property(name = "updated_at")
    private Instant updatedAt;

    public CategoryEntity() {
    }

    public CategoryEntity(String id, String name, String description, boolean isPrimary, Set<CategoryEntity> subCategories, Instant createdAt, Instant updatedAt) {
        this.id = id;
        this.name = name;
        this.description = description;
        this.isPrimary = isPrimary;
        this.subCategories = subCategories == null ? new HashSet<>() : subCategories;
        this.createdAt = createdAt;
        this.updatedAt = updatedAt;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public boolean isPrimary() {
        return isPrimary;
    }

    public void setPrimary(boolean primary) {
        isPrimary = primary;
    }

    public Set<CategoryEntity> getSubCategories() {
        return subCategories;
    }

    public void setSubCategories(Set<CategoryEntity> subCategories) {
        this.subCategories = subCategories;
    }

    public Instant getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Instant createdAt) {
        this.createdAt = createdAt;
    }

    public Instant getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Instant updatedAt) {
        this.updatedAt = updatedAt;
    }
}

内容的提问来源于stack exchange,提问作者user22349142

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 06:25:12