RavenDB:将数据库中的文档与来自外部源的数据同步

本文关键字:外部 同步 数据 文档 数据库 RavenDB | 更新日期: 2023-09-27 18:37:01

RavenDB中同步文档的最有效方法是什么?

从外部来源,我得到了IEnumerable博客文章,我想用它执行以下操作:

  • 添加 RavenDB 的新对象
  • 更新现有对象
  • 删除在外部源中删除的对象

需要实现的代码:

public void SyncIntoRaven(IEnumerable<BlogPost> postsToSync, IDocumentStore store) {
    // TODO: Implement
    // AddNewItems(postsToSync);
    // TODO: Implement
    // RemoveDeletedItems(postsToSync);
    // TODO: Implement
    // UpdateExistingItems(postsToSync);
}

人们可以从RavenDB中提取所有BlogPosts并在本地同步,然后将所有更改推送回去,但我想尽量减少RavenDB的流量。但也许这也不是正确的方法?

RavenDB:将数据库中的文档与来自外部源的数据同步

如果您在外部源和 RavenDB 之间共享相同的 ID,则可以在一个事务中以 ACID 方式非常轻松地执行此操作。

跟踪在同步操作之间更改的 ID,获得该 ID 列表后,您可以轻松完成此操作:

打开会话,使用会话添加新文档。Store(),使用会话加载所有需要更新或删除的文档。加载(字符串[])会话。加载()。懒洋洋地进行更新(并使用"延迟"选项进行删除),并在完成呼叫会话后进行。保存更改()。

这应该可以覆盖您,并且只需一次往返服务器即可完成。

无论哪种方式,您都不想每次都进行完全同步。您始终希望使用增量。

在 synhershko 的描述形式的帮助下,我想通了它,并希望分享代码,简化以显示概念。

private void RefreshBlogPosts(IDocumentSession session, IList<BlogPost> parsedPosts) {
    var parsedPostsIds = parsedPosts.Select(x => x.Id);
    var storePosts = session.Load<BlogPost>(parsedPostsIds);
    // Update existing or create new posts
    for(int i = 0; i < storePosts.Count(); i++) {
        var parsedPost = parsedPosts[i];
        var storePost = storePosts[i];
        if(storePost == null) {
            storePost = parsedPost;
            session.Store(storePost);
        } else {
            // Update post's properties
        }
    }
    // Find posts IDs no longer in database
    var removedPostIds = session.Query<BlogPost>().Select(x => x.Id)
        .Where(postId => !parsedPostsIds.Contains(postId));
    foreach(var removedPostId in removedPostIds) {
        session.Advanced.Defer(new DeleteCommandData() { Key = removedPostId });
    }
    session.SaveChanges();
}