我正在编写一个 XQuery 来分析存储类似于下面示例的查询的大量 XML 文件。对于这些查询,我想计算各种子元素的平均值、总和和其他信息。此外,我想在同一个文档中生成查询的子部分,例如所有没有命中的查询。
由于我将处理数十万个 XML 文件,因此我想让我的 xquery 尽可能高效。我尝试for
在文档中使用单次迭代,但我根本无法弄清楚如何获取我需要的所有信息。
这是一个示例 XML:
<Query>
<QueryString>Gigabyte Sapphire GTX-860</QueryString>
<StatusCode>0</StatusCode>
<QueryTime>0.04669069110297385</QueryTime>
<Hits>8</Hits>
<Date>2013-05-02</Date>
<Time>12:07:07</Time>
<LastModified>12:07:07</LastModified>
<Pages resultsPerPage="10" clickCount="2">
<Page resultCount="8" visited="true">
<Result index="1" clickIndex="0" timeViewed="0" pid="85405" title="DDR3 1024 MB" />
<Result index="2" clickIndex="1" timeViewed="178" pid="54065" title="ATK Excellium	" />
<Result index="3" clickIndex="0" timeViewed="0" pid="74902" title="Intel E9650" />
<Result index="4" clickIndex="0" timeViewed="0" pid="56468" title="ASUS Radeon HD 7980" />
<Result index="5" clickIndex="0" timeViewed="0" pid="31072" title="Intel E7500" />
<Result index="6" clickIndex="0" timeViewed="0" pid="26620" title="DDR3 2048 MB" />
<Result index="7" clickIndex="2" timeViewed="92" pid="55625" title="Gigabyte Sapphire 7770" />
<Result index="8" clickIndex="0" timeViewed="0" pid="67701" title="Intel E9650" />
</Page>
</Pages>
</Query>
这是 XQuery:
let $doc := collection('file:///C:/REP/XML/input?select=*.xml')
for $y in (
<Queries>
{
for $x in $doc
let $hits := $x/Query/Hits
return <Query hits="{$hits}" >{$x/Query/QueryString/string()}</Query>
}
</Queries>
)
let $avgHits := avg(data($y/Query/@hits))
let $numQueries := count($y/*)
return <Statistics avgHits="{$avgHits}" numQueries="{$numQueries}"/>
正确返回<Statistics numQueries="10" avgHits="19.7"/>
10 个 XML 文件的样本。这是正确的方法吗?我似乎需要双精度,所以我可以将不相交文件中的查询分组在一起,因为否则我似乎无法在它们上运行函数。
我还需要在创建的<Statistics>
元素中重复一些查询。我需要重复 FLWOR 语句吗?我不能将求和值或平均值带到计算它们的 for 语句之外,但我无法计算它们并执行子选择,因为我必须包含过滤它们的位置。
(更新)这是我想出的包含查询子部分的查询,但正如我提到的,我担心性能。
let $doc := collection('file:///C:/REP/XML/input?select=*.xml')
for $y in (
<Queries>
{
for $x in $doc
let $hits := $x/Query/Hits
return <Query hits="{$hits}" >{$x/Query/QueryString/string()}</Query>
}
</Queries>
)
let $avgHits := avg(data($y/Query/@hits))
let $numQueries := count($y/*)
return <Statistics avgHits="{$avgHits}" numQueries="{$numQueries}">
{
for $x in $doc
let $hits := $x/Query/Hits
where $x/Query/Hits < 10
return <Query hits="{$hits}" >{$x/Query/QueryString/string()}</Query>
}
</Statistics>
XQuery 处理器会优化我的 for 语句,还是会通过每个 for that 循环访问所有 XML 文件?第一let
条语句会阻止这种情况吗?
这是我要生成的文档类型:
<DailyStats date="2013-04-15" >
<DayStats>
<QueryCount>24644</QueryCount>
<Errors>0</Errors>
<EmptySearches>643</EmptySearches>
<AverageSearchTime>0.0213</AverageSearchTime>
<AverageSearchesPerHour>236</AverageSearchesPerHour>
</DayStats>
<StoredQueries>
<FailedSearches>
<FailedSearch time="23:33:34" query="blurey" searchTime="0.0524" />
</FailedSearches>
</StoredQueries>
</DailyStats>