【问题标题】:How to do batch insert of data in GraphDB in transaction如何在事务中在 GraphDB 中批量插入数据
【发布时间】:2019-10-11 20:21:03
【问题描述】:

我正在尝试将数据插入 GraphDB,因此 SPARQL 更新查询由总大小约为 1M 的语句组成,其中包含一些 DELETE 和 WHERE 语句。 我使用 GraphDB REST API 失败了:

1) 成功启动交易 POST /repositories/{repositoryID}/transactions 2) 发送更新请求(python中的代码sn-p)

requests.put(
    url='/repositories/{repositoryID}/transactions/{transactionID}'
    params={'update': sparql, 'action': 'ADD'}
) 

遇到错误

<!doctype html><html lang="en"><head><title>HTTP Status 400 – Bad Request</title><style type="text/css">h1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} h2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} h3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} b {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} p {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;} a {color:black;} a.name {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400 – Bad Request</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> Request header is too large</p><p><b>Description</b> The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).</p><p><b>Exception</b></p><pre>java.lang.IllegalArgumentException: Request header is too large

此 sparql 语句在 Workbench SPARQL 控制台中成功执行。但是如果我增加我得到的数据数量

java.lang.StackOverflowError

在工作台 UI 中。

我要执行的sparql是以下

PREFIX time: <http://www.w3.org/2006/time#> 
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> 
PREFIX tr: <http://www.semanticweb.org/tr#> 
PREFIX owl: <http://www.w3.org/2002/07/owl#>  
PREFIX geosparql: <http://www.opengis.net/ont/geosparql#>

DELETE { tr:ontologyVersion tr:hasTimestamp ?o . }
INSERT {
    trip:ontologyVersion a time:Instant, owl:NamedIndividual ; 
                     trip:hasTimestamp "2019-10-11 14:56:06.750130+00:00"^^xsd:dateTime . 

    <a lot of new triples>
} 
WHERE { 
    OPTIONAL { tr:ontologyVersion tr:hasTimestamp ?o . } 
} 

那么如何将数据插入GraphDB,正确的做法是什么?

更新 1

我重写了代码来使用

requests.put(url=url, data={'update': sparql}, params={'action': 'COMMIT'}) 

并使用 sparql = "DELETE DATA {}; INSERT DATA {}"。请求已完成,响应代码为 200,但由于某些原因数据不在 GraphDB 中。

更新 2

根据The rdf4j server REST API我将请求改为

requests.put(url=transaction_url, data={'update': sparql}, params={'action': 'UPDATE'}) 
requests.put(url=transaction_url, params={'action': 'COMMIT'}) 

仍然使用 sparql = "DELETE DATA {}; INSERT DATA {}"。 内容类型为 'application/x-www-form-urlencoded' 和 url 编码的 sparql 字符串的请求。

在这种情况下,我会收到 406 错误

org.eclipse.rdf4j.http.server.ClientHTTPException: Could not read SPARQL update string from body.

【问题讨论】:

  • 目前还不清楚您到底尝试了什么,出了什么问题。您能否更详细地说明您正在尝试做什么以及失败的地方?
  • 请不要在问题文本中提供答案,而是将其发布为作为答案,然后将其标记为已接受的答案。这样,其他有相同问题的人可以更轻松地找到它。
  • 另外:REST API 已在此处完整记录:rdf4j.eclipse.org/documentation/rest-api。可能比通过源代码更容易:)

标签: sparql graphdb


【解决方案1】:

这里有两个不同的问题。

第一个问题是当您尝试将 sparql 更新作为事务的一部分执行时。错误消息是“请求标头太大”。在我看来,这听起来像是您的请求正在尝试将有效负载作为标头字段发送,而不是作为数据有效负载。我想你可能想稍微改变一下你的 Python 代码,比如:

requests.put(
    url='/repositories/{repositoryID}/transactions/{transactionID}'
    data={'update': sparql, 'action': 'ADD'}
) 

(所以data 而不是params

第二个问题听起来像是 Workbench UI 的限制(假设这是引发 StackOverflowError 的原因),但除此之外,您插入新数据的方式非常低效:您正在执行可选查询作为一部分批量数据上传,以及使用 INSERT...WHERE。

我建议改为使用 INSERT DATA 命令进行批量上传:

INSERT DATA {
  // ... large amount of triples
}

如果您对时间戳所做的这件事应该是您想要实现的目标的一部分,我建议您在批量上传之前或之后作为单独的操作对该时间戳进行查询和更新 - 如果您这样做了在同一笔交易中,最终结果将是相同的。

哦,当然,一旦你完成了,你需要commit your transaction

【讨论】:

  • 我重写了代码以使用``` requests.put(url=url, data={'update': sparql}, params={'action': 'COMMIT'}) ```并使用 sparql = "DELETE DATA {}; INSERT DATA {}"。请求完成,响应代码为 200,但由于某些原因数据不在 GraphDB 中。
【解决方案2】:

最后,我想出了解决方案。

requests.put(url=transaction_url, data=sparql, params={'action': 'UPDATE'}, headers={'Conteny-Type': 'application/sparql-update'}) 
requests.put(url=transaction_url, params={'action': 'COMMIT'}) 

事实证明,RDF4J 事务 API 期望查询在正文中保持原样,没有任何 urlencoding 和 'update=' 参数名称。在这里找到它java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionController.java

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2014-08-11
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    相关资源
    最近更新 更多