簡體   English   中英

ArangoDB get_or_create 文檔的最佳方式

[英]ArangoDB best way to get_or_create a document

我正在執行我想象的索引圖形數據庫的常見模式:我的數據是一個邊列表,我想“流式傳輸”這些數據的上傳。 即,對於每條邊,我想在每一邊創建兩個節點,然后在它們之間創建邊; 我不想先上傳所有節點,然后再鏈接它們。 一個幼稚的實現顯然會導致很多重復的節點。 因此,我想實現某種“get_or_create”以避免重復。

我當前的實現如下,使用 pyArango:

def get_or_create_graph(self):
    db = self._get_db()
    if db.hasGraph('citator'):
        self.g = db.graphs["citator"]
        self.judgment = db["judgment"]
        self.citation = db["citation"]
    else:
        self.judgment = db.createCollection("judgment")
        self.citation = db.createCollection("citation")
        self.g = db.createGraph("citator")


def get_or_create_node_object(self, name, vertex_data):
    object_list = self.judgment.fetchFirstExample(
            {"name": name}
            )
    if object_list:
        node = object_list[0]
    else:
        node = self.g.createVertex('judgment', vertex_data)
        node.save()
    return node

我對這個解決方案的問題是:

  1. 由於應用程序而不是數據庫正在檢查存在性,因此存在性檢查和創建之間可能存在插入。 我在實踐中發現了重復的節點,我懷疑這是為什么?
  2. 它不是很快。 可能是因為它可能兩次擊中數據庫。

我在徘徊是否有更快和/或更原子的方式來做到這一點,理想情況下是原生 ArangoDB 查詢? 建議? 謝謝你。

更新根據要求,調用如下所示的代碼。 它在 Django 上下文中,其中 Link 是一個 Django 模型(即數據庫中的數據):

        ... # Class definitions etc

        links = Link.objects.filter(dirty=True)

        for i, batch in enumerate(batch_iterator(links, limit=LIMIT, batch_size=ITERATOR_BATCH_SIZE)):
            for link in batch:
                source_name = cleaner.clean(link.case.mnc)
                target_name = cleaner.clean(link.citation.case.mnc)

                if source_name == target_name: continue 

                source_data = _serialize_node(link.case)
                target_data = _serialize_node(link.citation.case)

                populate_pair(citation_manager, source_name, source_data, target_name, target_data, link)

def populate_pair(citation_manager, source_name, source_data, target_name, target_data, link):
    source_node = citation_manager.get_or_create_node_object(
        source_name,
        source_data
        )
    target_node = citation_manager.get_or_create_node_object(
        target_name,
        target_data
        )
    description = source_name + " to " + target_name
    citation_manager.populate_link(source_node, target_node, description)

    link.dirty = False
    link.save()

這是清理和序列化后數據的示例:

source_data: {'name': 'P v R A Fu', 'court': 'ukw', 'collection': 'uf', 'number': 'CA 139/2009', 'tag': 'NA', 'node_id': 'uf89638', 'multiplier': '5.012480529547776', 'setdown_year': 0, 'judgment_year': 0, 'phantom': 'false'}
target_data: {'name': 'Ck v R A Fu', 'court': 'ukw', 'collection': 'uf', 'number': '10/22147', 'tag': 'NA', 'node_id': 'uf67224', 'multiplier': '1.316227766016838', 'setdown_year': 0, 'judgment_year': 0, 'phantom': 'false'}
source_name: [2010] ZAECGHC 9
target_name: [2012] ZAGPJHC 189

我不知道 Python 驅動程序。 但這可以使用 AQL 來完成

FOR doc in judgement
Filter doc.name == "name"
Limit 1
Insert merge((vertexobject, { _from: doc.id }) into citator

vertextObject需要是一個至少具有_to值的 AQL 對象

注意 我用手機接聽時可能有錯別字

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM