繁体   English   中英

MarkLogic:将数据写入查询中的文档,然后在同一查询中访问这些文档

[英]MarkLogic: write data to documents in query and then access those documents in the same query

在MarkLogic中,我想编写创建文档/地图的函数,然后在该查询中访问这些文档/地图-我相信这样做可以避免内存问题/超时。

但是,除非我在单独的查询中运行每个函数,否则代码将无法工作。 如何强制一个功能仅在另一个功能完全完成后才能运行:即将文档保存到磁盘?

编辑:我的问题是我想找到两个元素的不同值,例如和在文档集合中。 我还想知道这些元素的值的每种组合出现的频率。

我希望能够创建的结果看起来像是在文档集合中,每个文档包含一个包含id的元素和一个包含代表人的字符串的元素:

<pairs>
    <pair frequency="5">
       <thing-1>01257</thing-1>
       <thing-2>John Smith</thing-2>
    </pair>
</pairs>

这是我一直在使用的代码:

xquery version "1.0-ml";
declare namespace local = "http://www.local.com";

declare variable $collections := 'A' ;
declare variable $query-name := 'A-query' ;
declare variable $number-of-documents := count(collection($collections)) ; 
declare variable $map-collection := concat ($query-name, '-maps') ;

(: create a temporary collection to store data saved during the query :)
declare function local:document-set-creator($counter, $iteration) {
 if ($counter > ($number-of-documents + 1000)) 
  then ()
   else (
    let $name := concat($query-name, '-part', $iteration) 
         let $uris := for $i in subsequence(cts:uris( (), (), cts:collection-query($collections) ), $counter, 1000) return $i 
     let $results := 
                <results>
                    {
                        for $i in $uris
                            let $thing-1 := cts:search(/*/element/thing-1 , cts:document-query($i) )
                            let $thing-2 := cts:search(/*/element/thing-2 , cts:document-query($i) )
                          return
                                <pair>
                                 <thing1>{$thing-1/normalize-space(string())}</thing1>
                                 <thing2>{$thing-2/normalize-space(string())}</thing2>
                                </pair>
                            }
                    </results>   
            let $path-name := concat('pairs-', $name, '.xml') 

      return
        xdmp:document-insert($path-name , $results, (), $query-name )
         ,
        xdmp:sleep(1000)
          ,
        local:document-set-creator(($counter + 1000), ($iteration + 1))

    )
} ;

(: take values from the pairs list, concatenate them and put them into a map
  key = concatenated value
  value = frequency
 :) 
 declare function local:create-pair-maps() {
     for $i in collection($query-name) 
     return
        local:write-maps(base-uri($i))
 } ;

  declare function local:write-maps($uri) {
   let $document := doc($uri) 
   let $output-document := concat(substring-before(string($uri), '.xml') , '-MAP.xml')
   let $value-map := map:map()
   let $fill-the-map := for $pair in $document//pair 
                          let $thing-1 := $pair/courtname/string()
                            let $thing-2 := $pair/courtcode/string() 
                            let $value := concat($thing-1, '_', $thing-2)
                            return
                                    if ( $value = map:keys($value-map) )
                                   then map:put($value-map , $value ,
                                        (map:get($value-map , $value) + 1) )
                                   else map:put($value-map , $value , 1)
  let $map-container := <container>{$value-map}</container>

  return
    xdmp:document-insert($output-document , $map-container, (), $map-collection ) 

} ;


(: combine maps :)
declare function local:combine-maps() {
   let $maps := for $i in collection($map-collection) return $i
   let $output-document := concat($query-name, '-combined-map.xml')
   let $value-map-2 := map:map()
   let $fill-the-map := for $_m in $maps
                          let $m := map:map($_m/container/map:map)
                            for $key in map:keys($m)
                              return
                                if ($key = map:keys($value-map-2))
                                                                then map:put($value-map-2 , $key ,
                                                            (map:get($value-map-2 , $key) + map:get($m , $key)))
                                                                   else map:put($value-map-2 , $key , map:get($m , $key))
  let $map-container := <container>{$value-map-2}</container>
  return
    xdmp:document-insert($output-document , $map-container, (), $map-collection)
} ;

(: write results to spreadsheet-friendly XML structure :)
declare function local:maps-to-spreadsheet() {
  let $input-document-name := concat($query-name , '-combined-map.xml')
  return
   <results>{
      for $i in doc($input-document-name)/container/map:map/map:entry
        let $thing-2 := substring-before($i/@key/string(), '_')
        let $thing-1 := substring-after($i/@key/string(), '_')
        order by $thing-2
        return
           <pair frequency="{$i/map:value/string()}">
             <thing-1>{$thing-1}</thing-1>
             <thing-2>{$thing-1}</thing-2>
          </pair>
     }
   </results>
};

local:document-set-creator(1, 1) ,
local:create-pair-maps()  ,
local:combine-maps() ,
local:maps-to-spreadsheet() 

与其构建自己的频率计数文档,不如考虑将https://docs.marklogic.com/cts:valueshttps://docs.marklogic.com/cts:value-co-occurrences与范围索引一起使用。 尝试使用带有这些功能的map选项。 与您自己构建类似功能相比,这应该更快,更可靠。

就是说,您可能对多语句事务感兴趣: https : //docs.marklogic.com/guide/app-dev/transactions-我写了一个可能对您有帮助的教程: http : //blakeley.com/blogofile/ 2013/06/21 /多语句交易简介

但是,使用MST可能无法解决内存消耗或超时的原始问题。 与仅在函数之间传递map:map项相比,通过插入这些临时文档,您可能最终会占用更多的内存和更多的时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM