我使用XPath从XML文件中提取大块。我的xml文件很大,它们来自PubMed。我的文件类型的一个例子是:
ftp://ftp.ncbi.nlm.nih.gov/pubmed/baseline/medline17n0001.xml.gz
所以,使用
Node result = (Node)xPath.evaluate("PubmedArticleSet/PubmedArticle[MedlineCitation/PMID = "+PMIDtoSearch+"]", doc, XPathConstants.NODE);
我收到PMIDtoSearch的文章,所以它很完美。但这需要很长时间。我必须做大约800.000次,所以使用这个解决方案需要两个多月。有些块有超过400行,每个xml文件有超过4百万行。
我也尝试了类似getElementsByTagName
函数的解决方案,但它几乎需要相同的时间。
您知道如何改进解决方案吗?
感谢。
答案 0 :(得分:4)
我把你的文件加载到exists-db然后执行你的查询,基本上是这样的:
xquery version "3.0";
let $medline := '/db/Medline/Data'
let $doc := 'medline17n0001.xml'
let $PMID := request:get-parameter("PMID", "")
let $article := doc(concat($medline,'/',$doc))/PubmedArticleSet/PubmedArticle[MedlineCitation/PMID=$PMID]
return
$article
文档在400毫秒内从远程服务器返回。如果我加强了那个服务器,我会期望少于那个,它可以处理多个并发请求。或者如果你在当地拥有更快的东西。
亲自尝试,我将数据留在测试服务器中(并记住这是在远程查询加利福尼亚的亚马逊微服务器):
http://54.241.15.166/get-article2.xq?PMID=8
http://54.241.15.166/get-article2.xq?PMID=6
http://54.241.15.166/get-article2.xq?PMID=1
当然,整个文件都在那里。您只需将该查询更改为PMID = 667或999或其他任何内容,然后返回目标文档片段。
答案 1 :(得分:2)
正如@KevinBrown建议的那样,数据库可能是正确的答案。但是,如果这是一次性流程,那么可能解决方案比您的解决方案更快,但不需要学习如何设置XML数据库的复杂性。
在您使用的方法中,有两个主要成本:解析XML文档以在内存中创建树,然后搜索内存中的文档以查找特定的ID值。我猜想解析成本可能比搜索成本高出一个数量级。
因此,有两个要素可以获得良好的表现:
首先,您需要确保只解析每个源文档一次(而不是每个查询一次)。你还没告诉我们足够让我知道你是否已经这样做了。
第二,如果要从单个文档中检索许多数据块,则需要在不对每个文档进行序列搜索的情况下执行此操作。实现此目的的最佳方法是使用构建索引的查询处理器来优化查询(例如Saxon-EE)。或者,您可以“手动”构建索引,例如使用XQuery 3.1映射,或者使用XSLT中的xsl:key功能。
答案 2 :(得分:0)
这是在我的笔记本电脑上执行xpath查询的代码..结果看起来不错......不管pmid值如何都需要大约1秒。你打算如何提取文本。我可以更新代码来定位。
['class' => 'yii\grid\ActionColumn',
'template' => '{view} {update} {delete}', //{view}
'buttons' => [
'view' => function($url, $model) {
return Html::a('<button class="btn btn-success">View <i class="glyphicon glyphicon-eye-open"></i></button>',$url);
},
'update' => function($url, $model) {
return Html::a('<button class="btn btn-primary">Update <i class="glyphicon glyphicon-pencil"></i></button>',$url);
},
'delete' => function($url, $model) {
return Html::a('<button class="btn btn-danger">Delete <i class="glyphicon glyphicon-trash"></i></button>', $url,
['data-confirm' => 'Are you sure you want to delete this item?', 'data-method' =>'POST']
);
},
'urlCreator' => function($action, $model, $key, $index) {
if ($action == 'view') {
return Html::a('Action', $url);
}
if ($action == 'update') {
return Html::a('Action', $url);
}
if ($action == 'delete') {
return Html::a('Action', $url);
}
}
],
], // fin ActionColumn