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

非二叉树(无自然排序)节点插入问题(Java Spring Boot+MongoDB)

实现指定父节点的场景节点插入

针对你的Spring Boot+MongoDB冒险故事应用,要完成新节点挂载到指定父节点的需求,可按以下步骤修改代码:

1. 完善SceneNode的节点查找与插入逻辑

先给childNodes初始化避免空指针,添加递归查找父节点并插入子节点的方法,同时限制子节点数量不超过5:

public class SceneNode {
    @Id
    private String storyId;
    private String parentId;
    private String option;
    private String description;
    // 初始化子节点列表,防止空指针异常
    private List<SceneNode> childNodes = new ArrayList<>();

    // 修正构造方法的拼写错误(descrtion -> description)
    public SceneNode(String parentId, String option, String description) {
        this.parentId = parentId;
        this.option = option;
        this.description = description;
    }

    // 递归查找目标父节点并添加子节点
    public boolean addChild(String targetParentId, SceneNode newNode) {
        // 当前节点是目标父节点时,添加子节点
        if (this.storyId.equals(targetParentId)) {
            if (childNodes.size() >= 5) {
                throw new IllegalArgumentException("单个场景最多支持5个子节点");
            }
            childNodes.add(newNode);
            return true;
        }
        // 遍历子节点继续查找
        for (SceneNode child : childNodes) {
            if (child.addChild(targetParentId, newNode)) {
                return true;
            }
        }
        return false;
    }

    // getters & setters 省略
}

2. 改造StoryTree的insert方法

处理根节点创建逻辑,调用递归方法完成子节点插入:

public class StoryTree {
    private SceneNode root;

    public void insert(String parentId, String option, String description) {
        SceneNode newScene = new SceneNode(parentId, option, description);
        if (root == null) {
            // 根节点的parentId必须为空或null,作为故事起点
            if (parentId == null || parentId.isEmpty()) {
                root = newScene;
            } else {
                throw new IllegalArgumentException("根节点的parentId不能指定");
            }
        } else {
            boolean inserted = root.addChild(parentId, newScene);
            if (!inserted) {
                throw new IllegalArgumentException("未找到ID为" + parentId + "的父节点");
            }
        }
    }

    // getters & setters 省略
}

3. 适配MongoDB持久化

因为使用MongoDB,可根据故事体量选择两种存储方式:

方式一:嵌入式存储(子节点嵌入父节点文档)

适合小体量故事树,查询时可一次性获取整棵树。保存父节点时需同步更新子节点列表:

@Repository
public interface SceneNodeRepository extends MongoRepository<SceneNode, String> {
}

@Service
public class StoryService {
    @Autowired
    private SceneNodeRepository repo;

    public SceneNode insertScene(String parentId, String option, String description) {
        SceneNode newNode = new SceneNode(parentId, option, description);
        if (parentId == null || parentId.isEmpty()) {
            // 保存根节点
            return repo.save(newNode);
        }
        // 查找父节点并添加子节点
        SceneNode parent = repo.findById(parentId)
                .orElseThrow(() -> new IllegalArgumentException("父节点不存在"));
        parent.addChild(parentId, newNode);
        // 先保存子节点生成ID,再更新父节点
        newNode = repo.save(newNode);
        repo.save(parent);
        return newNode;
    }
}

方式二:引用式存储(子节点仅存父ID)

适合大型故事树,避免单文档过大。插入时只需保存子节点的parentId:

@Repository
public interface SceneNodeRepository extends MongoRepository<SceneNode, String> {
    List<SceneNode> findByParentId(String parentId);
}

@Service
public class StoryService {
    @Autowired
    private SceneNodeRepository repo;

    public SceneNode insertScene(String parentId, String option, String description) {
        if (parentId != null && !parentId.isEmpty()) {
            // 校验父节点存在
            repo.findById(parentId)
                    .orElseThrow(() -> new IllegalArgumentException("父节点不存在"));
        }
        SceneNode newNode = new SceneNode(parentId, option, description);
        return repo.save(newNode);
    }

    // 查询指定父节点的所有子节点
    public List<SceneNode> getChildren(String parentId) {
        return repo.findByParentId(parentId);
    }
}

核心注意事项

  • 确保storyId唯一:MongoDB的@Id注解会自动生成唯一的ObjectId,无需手动维护
  • 严格控制子节点数量:在addChild方法中添加校验,符合业务要求
  • 异常处理:针对父节点不存在、子节点超限等场景抛出明确异常,便于上层捕获处理

内容的提问来源于stack exchange,提问作者Dr.M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 13:36:30