楼主: zizhu123
44 0

[作业] 用spring data neo4j批量插入节点关系 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

80%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
30 点
帖子
2
精华
0
在线时间
0 小时
注册时间
2018-9-20
最后登录
2018-9-20

楼主
zizhu123 发表于 2025-11-21 17:08:18 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
最近在使用 Java 开发基于 neo4j 的图谱项目时,遇到了一些实际问题。Spring Data Neo4j(SDN)并未对所有操作提供封装,这一点在处理批量插入节点关系时尤为明显。可能是个人经验有限,并未找到现成的解决方案,查阅官方文档及其他参考资料后,依然未能满足需求,因此决定自行实现。 通过研究 Cypher 语法,最终采用 UNWIND 构建语句的方式,实现了对节点间关系的批量操作。该方法能够有效提升数据写入效率,适用于大规模关系导入场景。
@Data
public class PersonToMovie {
    private String movieId;
    private String personId;
    private String typeCode;
    private String commonId;
}



public class CypherUtil {

    public static String fieldNameBuild(String resource) {
        // 正则表达式:匹配 "字段名":(字段名由字母、数字、下划线组成)
        Pattern pattern = Pattern.compile("\"([a-zA-Z0-9_]+)\":");
        Matcher matcher = pattern.matcher(resource);
        // 替换为:字段名:(去掉引号)
        return matcher.replaceAll("$1:");
    }

}


@NoArgsConstructor
@AllArgsConstructor
public enum RelationTypeEnum  {
    CONTAINS( "CONTAINS", 1),
    RELATED("RELATED", 2),
    ORDER( "ORDER", 3),
    BE_CONTAINS("BE_CONTAINS", 4),
    BE_ORDER("BE_ORDER", 5);

    private String typeCode;
    private Integer typeCodeNum;


    public static RelationTypeEnum  getKnowledgePointRelationType(String typeCode) {
        for (RelationTypeEnum value : RelationTypeEnum.values()) {
            if (value.getTypeCode().equals(typeCode)) {
                return value;
            }
        }
        return null;
    }

    public static RelationTypeEnum getKnowledgePointRelationType(Integer typeCodeNum) {
        for (RelationTypeEnum value : RelationTypeEnum.values()) {
            if (value.getTypeCodeNum().equals(typeCodeNum)) {
                return value;
            }
        }
        return null;
    }

    public String getTypeCode() {
        return typeCode;
    }

    public Integer getTypeCodeNum() {
        return typeCodeNum;
    }

}


public interface PersonToMovieRelationService {
    boolean batchSave(RelationTypeEnum relationType, List<PersonToMovie> relationDtos);

}


@Service
public class PersonToMovieRelationServiceImpl implements PersonToMovieRelationService {

    @Autowired
    private Neo4jClient neo4jClient;


    @Override
    public boolean batchSave(RelationTypeEnum relationType, List<PersonToMovie> relationDtos) {
        String query = """
                 UNWIND $dtoList AS dto
                 MERGE (p:Person {id: dto.personId, commonId: dto.commonId})
                 MERGE (m:Movie {id: dto.movieId, commonId: dto.commonId})
                 with p,m MERGE (p)-[:$relationType]->(m) RETURN p, m;
                """;
        String saveStr = JSON.toJSONString(relationDtos);
        String finalQuery = query.replace("$relationType", relationType.getTypeCode()).replace("$dtoList", CypherUtil.fieldNameBuild(saveStr));
        neo4jClient.query(finalQuery).run();
        return true;
    }
}
需要注意的是,neo4j 不支持通过参数动态命名关系。这意味着无法在一个语句中灵活地创建不同类型的关系名称。若确实需要实现动态关系命名,可考虑引入 APOC 插件来扩展功能。但在常规情况下,建议将待插入的关系按类型分类,针对每种关系类型分别调用批量保存方法,以完成整体的数据写入任务。 对于有类似需求的开发者,此方案可作为参考。若各位有更好的实现方式,欢迎交流探讨。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Spring Pring RING Data ING

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-25 06:03