暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

比较JSON文档并使用TerminusDB和MongoDB应用补丁

原创 eternity 2022-08-12
419

在本演示教程中,我们将展示如何应用差异和修补操作来监控TerminuDB模式、TerminuSB文档、JSON模式和其他文档数据库(如MongoDB)中的更改。

关于JSON、差异和补丁的一点背景知识

Git分布式管理源代码策略中的一个基本工具是diff和补丁的概念。这些基本操作使git成为可能。Diff用于构造可应用于对象的面片,以使最终状态对某些值有意义。

但是结构化数据呢?对于需要差异和修补操作的结构化数据,是否会出现类似情况?当然有。

在应用程序中,当两个或多个用户更新同一对象时,例如在线商店,通常通过锁定对象来实现这种管理操作。这意味着只有一个人能赢。锁是一个巨大的痛苦来源,这不仅是因为你无法实现完全合理的并发操作,还因为你可能会遇到过时的锁,并不得不决定何时释放它们。

当多人处理数据集时,往往会发生冲突。如果没有足够的工作流程和冲突度量,经常会有人的更改被压扁,因此,数据可能开始变得不准确。从长远来看,这会导致报告、客户服务和商业智能方面的各种问题。这就是diff和patch的用武之地,用户可以在每次向数据库提交更改时看到前后状态。在这里,任何冲突都可以标记出来,人工审查可以监督这些变化,以确保长期数据的准确性。更好的数据,更好的决策。

在TerminusDB Python中使用Diff和Patch

先决条件

您需要安装TerminusDB Python客户端,请查看此处。

确保Docker容器在本地主机上运行。

在这个脚本中,我们演示了diff如何返回一个补丁对象,通过该对象,您可以应用补丁来修改一个对象,我们为TerminusDB模式、TerminusDB文档和JSON模式展示了这一点。

在USDB中,文档和模式以JSON-LD格式表示。使用diff和patch,我们可以轻松地比较任何文档和模式,以查看发生了什么变化。

让我们将文档视为Python对象:

class Person(DocumentTemplate):
    name: str
    age: int 

jane = Person(name="Jane", age=18) 
janine = Person(name="Janine", age=18)
复制

您可以直接应用差异来获得面片对象:

result_patch = client.diff(jane, janine) 
pprint(result_patch.content)
复制

使用patch对象(这里是result_patch),您可以查看其内容,也可以将其应用于对象,然后返回after对象。

after_patch = client.patch(jane, result_patch) 

pprint(after_patch) 
assert after_patch == janine._obj_to_dict()
复制

如您所见,after_patch对象(文档)与janine相同。您可以使用replace_document将此文档放回数据库,以提交此更改。

Diff和patch还可用于JSON-LD文档:

jane = { "@id" : "Person/Jane", "@type" : "Person", "name" : "Jane"}
janine = { "@id" : "Person/Jane", "@type" : "Person", "name" : "Janine"} 

result_patch = client.diff(jane, janine) 

pprint(result_patch.content)
复制

它也不限于JSON-LD,它可以使用模式:

class Company(DocumentTemplate):
    name: str
    director: Person 

schema1 = WOQLSchema() 
schema1.add_obj("Person", Person) 
schema2 = WOQLSchema() schema2.add_obj("Person", Person) 
schema2.add_obj("Company", Company) 

result_patch = client.diff(schema1, schema2) 

pprint(result_patch.content)
复制

请注意,diff和patch将适用于大多数JSON格式。

另一个应用程序示例是比较2个JSON模式:

schema1 = {
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "birthday": { "type": "string", "format": "date" },
    "address": { "type": "string" },  } }

schema2 = {
  "type": "object",
  "properties": {
    "first_name": { "type": "string" },
    "last_name": { "type": "string" },
    "birthday": { "type": "string", "format": "date" },
    "address": {      
    "type": "object",
      "properties": {
        "street_address": { "type": "string" },
        "city": { "type": "string" },
        "state": { "type": "string" },
        "country": { "type" : "string" }
      }
    }
  }
 }

result_patch = client.diff(schema1, schema2) 

pprint(result_patch.content)
复制

请参阅此处的完整脚本

在MongoDB中使用Diff和Patch

在这个脚本中,我们演示了如何在MongoDB工作流中使用diff和patch。脚本的第一部分是关于如何使用Pymongo的MongoDB教程,在第二部分中,我们演示了在将修补程序应用到MongoDB集合之前检查更改的额外步骤。

正如我们在上一节中发现的,diff和patch可以应用于任何JSON格式。由于MongoBD也使用JSON格式来描述其数据,我们可以使用diff和patch来做类似的事情。

这里我们以Pymongo教程为例:

client = MongoClient(os.environ["MONGO_CONNECTION_STRING"]) 

# Create the database for our example (we will use the same database throughout the tutorial 
connection = client['user_shopping_list'] 

collection_name = connection["user_1_items"] 

item_1 = {
"_id" : "U1IT00001", 
"item_name" : "Blender", 
"max_discount" : "10%", 
"batch_number" : "RR450020FRG", 
"price" : 340, 
"category" : "kitchen appliance" 
}

item_2 = { 
"_id" : "U1IT00002", 
"item_name" : "Egg", 
"category" : "food", 
"quantity" : 12, 
"price" : 36, 
"item_description" : "brown country eggs" 
}
collection_name.insert_many([item_1,item_2]) 

expiry_date = '2021-07-13T00:00:00.000' 
expiry = dt.datetime.fromisoformat(expiry_date) 
item_3 = { "item_name" : "Bread", 
"quantity" : 2, 
"ingredients" : "all-purpose flour", 
"expiry_date" : expiry 
}
collection_name.insert_one(item_3)
复制

假设我们想要更改item_ 1:

new_item_1 = {
"_id" : "U1IT00001", 
"item_name" : "Blender", 
"max_discount" : "50%", 
"batch_number" : "RR450020FRG", 
"price" : 450, 
"category" : "kitchen appliance" 
}
复制

我们可以将新旧项目1与差异和补丁进行比较:

tbd_endpoint = WOQLClient("http://localhost:6363/") 

# Find the item back from database in case someone already changed it 
item_1 = collection_name.find_one({"item_name" : "Blender"}) 
patch = tbd_endpoint.diff(item_1, new_item_1) 

pprint(patch.content)
复制

同样,我们可以在MongoDB进行更改之前查看:

collection_name.update_one(patch.before, {"$set": patch.update})
复制

这是另一个更复杂的例子:

expiry_date = '2021-07-15T00:00:00.000' 
expiry = dt.datetime.fromisoformat(expiry_date) 
new_item_3 = { 
"item_name" : "Bread", 
"quantity" : 5, 
"ingredients" : 
"all-purpose flour", 
"expiry_date" : expiry 
}
 
item_3 = collection_name.find_one({"item_name" : "Bread"}) 
item_id = item_3.pop('_id') # We want to pop it out and optionally we can add it back 
patch = tbd_endpoint.diff(item_3, new_item_3) 

pprint(patch.content) 

# Add _id back, though it still works without 
before = patch.before 
before['_id'] = item_id 

collection_name.update_one(before, {"$set": patch.update})
复制

在MongoDB JavaScript中使用Diff和Patch

与上一节一样,可以使用diff和patch来比较文档和模式,以查看使用JavaScript客户端所做的更改。

在这个脚本中,我们将演示它。

我们创建了一个名为patchMongo的函数:

const mongoPatch = function(patch){
    let query = {};
    let set = {};

    if('object' === typeof patch){
        for(var key in patch){
            const entry = patch[key];

             if( entry['@op'] == 'SwapValue'){
                query[key] = entry['@before'];
                set[key] = entry['@after'];
            }else if(key === '_id'){
                query[key] = ObjectId(entry);
            }else{
                let [sub_query,sub_set] = mongoPatch(entry);
                query[key] = sub_query;
                if(! sub_set === null){
                    set[key] = sub_set;
                }
            }
        }
        return [query,set]
    }else{
        return [patch,null]
    } 
}
复制

我们创建了一个对象,可以放回去更新MongoDB中的数据:

let patchPromise = client.getDiff(jane,janine,{}); 
patchPromise.then( patch => {
    let [q,s] = mongoPatch(patch)
    console.log([q,s]);

    const res = db.inventory.updateOne(q, { $set : s});
    console.log(res);
    if (res.modifiedCount == 1){
        console.log("yay!")
    }else{
        console.log("boo!")
    }
    console.log(patch);
});
复制

原文标题:Compare JSON Documents and Apply Patches With TerminusDB and MongoDB
原文作者:Oliver Smith
原文链接:https://dzone.com/articles/compare-json-documents-and-apply-patches-with-term

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论