【问题标题】:Data gets mixed up while trying to transfer it to arangodb尝试将数据传输到 arangodb 时数据混淆了
【发布时间】:2017-11-16 21:50:59
【问题描述】:

我正在尝试转移 ca。 10GB 的 json 数据(在我的例子中是推文)到 arangodb 中的集合。我也在尝试使用 joblib:

from ArangoConn import ArangoConn
import Userdata as U

import encodings
from joblib import Parallel,delayed
import json
from glob import glob
import time


def progress(total, prog, start, stri = ""):
    if(prog == 0):
        print("")
        prog = 1;
    perc = prog / total
    diff = time.time() - start
    rem = (diff / prog) * (total - prog)
    bar = ""
    for i in range(0,int(perc*20)):
        bar = bar + "|"
    for i in range(int(perc*20),20):
        bar = bar + " "
    print("\r"+"progress: " + "[" + bar + "] " + str(prog) + " of " + 
    str(total) + ": {0:.1f}% ".format(perc * 100) + "- " + 
    time.strftime("%H:%M:%S", time.gmtime(rem)) + " " + stri, end="")

def processfile(filepath):
    file = open(filepath,encoding='utf-8')
    s = file.read()
    file.close()
    data = json.loads(s)
    Parallel(n_jobs=12, verbose=0, backend="threading"
    (map(delayed(ArangoConn.createDocFromObject), data))

files = glob(U.path+'/*.json')
i = 1
j = len(files)
starttime = time.time()
for f in files:
    progress(j,i,starttime,f)
    i = i+1
    processfile(f)

from pyArango.connection import Connection
import Userdata as U
import time


class ArangoConn:
    def __init__(self,server,user,pw,db,collectionname):
        self.server = server
        self.user = user
        self.pw = pw
        self.db = db
        self.collectionname = collectionname
        self.connection = None
        self.dbHandle = self.connect()
        if not self.dbHandle.hasCollection(name=self.collectionname):
            coll = self.dbHandle.createCollection(name=collectionname)
        else:
            coll = self.dbHandle.collections[collectionname]
        self.collection = coll

    def db_createDocFromObject(self, obj):
        data = obj.__dict__()
        doc = self.collection.createDocument()
        for key,value in data.items():
            doc[key] = value

        doc._key= str(int(round(time.time() * 1000)))
        doc.save()

    def connect(self):
        self.connection = Connection(arangoURL=self.server + ":8529",         
        username=self.user, password=self.pw)

        if not self.connection.hasDatabase(self.db):
            db = self.connection.createDatabase(name=self.db)
        else:
            db = self.connection.databases.get(self.db)
        return db

    def disconnect(self):
        self.connection.disconnectSession()


    def getAllData(self):

        docs = []
        for doc in self.collection.fetchAll():
            docs.append(self.doc_to_result(doc))
        return docs


    def addData(self,obj):
            self.db_createDocFromObject(obj)

    def search(self,collection,search,prop):
        docs = []
        aql = """FOR q IN """+collection+""" FILTER q."""+prop+""" LIKE 
            "%"""+search+"""%" RETURN q"""
        results = self.dbHandle.AQLQuery(aql, rawResults=False, batchSize=1)
        for doc in results:
            docs.append(self.doc_to_result(doc))
        return docs


    def doc_to_result(self,arangodoc):
        modstore = arangodoc.getStore()
        modstore["_key"] = arangodoc._key
        return modstore

    def db_createDocFromJson(self,json):

        for d in json:
            doc = self.collection.createDocument()
            for key,value in d.items():
                doc[key] = value
            doc._key = str(int(round(time.time() * 1000)))
            doc.save()



    @staticmethod
    def createDocFromObject(obj):
        c = ArangoConn(U.url, U.user, U.pw, U.db, U.collection)
        data = obj
        doc = c.collection.createDocument()
        for key, value in data.items():
            doc[key] = value
        doc._key = doc["id"]
        doc.save()
        c.connection.disconnectSession()

有点像这样。我的问题是数据库中的数据以某种方式混淆了。

正如您在屏幕截图中看到的那样,“id”和“id_str”并不相同——它们应该是。

到目前为止我调查了什么:

  • 我认为在某些时候数据库中的默认键可能会“冲突” 由于线程,所以我将密钥设置为推文 ID。

  • 我尝试在没有多个线程的情况下执行此操作。线程似乎不是 问题

  • 我查看了发送到数据库的数据...一切似乎都很好

但一旦我与数据库通信,数据就会混淆。

我的教授认为 pyarango 中的某些东西可能不是线程安全的,它会弄乱数据,但我不这么认为,因为线程似乎不是问题。

我不知道这种行为可能来自哪里...... 有什么想法吗?

【问题讨论】:

    标签: python multithreading arangodb joblib pyarango


    【解决方案1】:

    屏幕截图显示以下值:

    id     : 892886691937214500
    id_str : 892886691937214465
    

    它看起来像是在将值转换为 IEEE754 双精度的过程中的某个地方,它不能安全地表示后一个值。因此,转换可能会导致一些精度损失。

    node.js 中的一个简单示例(JavaScript 对任何大于 0xffffffff 的数值使用 IEEE754 双精度数)表明这可能是问题的原因:

    $ node
    > 892886691937214500
    892886691937214500
    > 892886691937214465
    892886691937214500
    

    所以问题是转换确实发生在哪里。您能否检查 python 客户端程序是否正确地将预期值发送到 ArangoDB,或者它是否已经发送了转换/截断的值?

    一般来说,任何超过 0x7fffffffffffffff 的整数在存储到 ArangoDB 时都会被截断,或者转换为 IEEE754 双精度数。这可以通过将数字值存储在字符串中来避免,但当然比较两个数字字符串会产生与比较两个数字不同的结果(例如 "10" < "9"10 > 9)。

    【讨论】:

    • 转换发生在 arangodb 中。我很确定那里,因为我在发送数据之前检查了数据。所以我唯一能做的就是把它保存为字符串?
    • 好的,您是否知道您使用哪些 ArangoDB API 来存储数据并从 ArangoDB 检索数据?这将帮助我们找出是否有任何转换/截断,以及在哪里。谢谢!
    • 我目前正在使用 Arangodb 3.1.28,但如果有帮助,升级将没有问题。在 python 方面,我正在使用 pyarango 。我不知道这是哪个版本的魔法:D
    • 我会检查是否有任何明显的东西导致 ArangoDB 的 REST 接口截断。
    • 只需检查一些 API 调用,确保 arangod 正确接收和存储最大为 0x7fffffffffffffff 的整数值,并且在将 REST 接口与 curl 一起使用时再次正确返回。但是,当使用 arangosh 时,它将截断任何更大的整数值,将它们转换为 IEEE754 双精度值。这是因为 JavaScript 没有具有足够精度的内置数字类型来处理这些值。当文档显示在 Web 界面中时,也会出现截断。同样的原因:JavaScript 中没有合适的数字类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 2019-06-01
    • 2014-01-01
    相关资源
    最近更新 更多