xmdp:http-get和xdmp:insert-document

时间:2012-04-15 20:52:23

标签: marklogic

我正在尝试使用marklogic XDMP API从twitter获取XML feed,我能够在Xquery控制台中获取XML,但无法弄清楚如何转换该xml并放入命名数据库。我正在做以下事情:

  1. 使用xdmp:http-get函数点击此网址“http://search.twitter.com/search.atom?q=pankaj&since_id=1212121”时,我会看到以下XML:

    <?xml version="1.0" encoding="UTF-8"?>
      <twitter>
        <entry>
          <id>1212121</id>
          <content>did u hear what he talked about Pankaj</content>
        </entry>
        <entry>
         <id>1212122</id>
          <content>abc xyz abc xyz</content>
        </entry>
     </twitter>
    
  2. 现在我想将此xml拆分为每个<entry>文档并插入marklogic数据库。

  3. 此脚本也应该每隔30秒安排一次,下一次点击应该在网址的since_id字段中附加最后一个条目的ID。
  4. 我正在尝试关注但收到一些错误,我也不知道在哪里提供数据库名称以及如何追加since_id

    let $content := xdmp:http-get("http://search.twitter.com/search.atom?q=pankaj&since_id=191622916163641344",
     <options xmlns="xdmp:document-get">
       <encoding>UTF-8</encoding>
     </options>)
    return  
    for $i in $content//entry
    return
    xdmp:document-insert(
         "/example.xml", $content//entry,
         xdmp:default-permissions(), 
         xdmp:default-collections(), 
     10)
    

2 个答案:

答案 0 :(得分:3)

一个错误可能是关于未转义的&符号的抱怨,它在XQuery(如XML)中需要使用&amp;进行转义。

您还需要声明Atom命名空间,因为从Twitter返回的内容将其用作默认命名空间。

您还希望为每个文档指定一个唯一的名称;否则,MarkLogic将抛出CONFLICTINGUPDATES错误。在下面的解决方案中,我在结果文档的URI中使用推文ID(从<atom:id>元素解析它)。

要更新since_id值,您有几个选项。不幸的是,来自Twitter的XML不包含原始推文ID作为其自身的元素或属性值,这意味着我们将无法在插入时首先修改文档而无法在其上创建范围索引(包括此类一个领域)。但我们可以利用我们在URI中使用推文ID这一事实。启用URI词典(管理界面中的全局数据库选项)将允许您调用cts:uris()以轻松获取您已存储的最新推文ID。

以下是我使用这种技术提出的完整解决方案:

declare namespace atom="http://www.w3.org/2005/Atom";
declare variable $initial-tweet-id := "191622916163641344";
declare variable $uri-prefix := "/tweets/";
declare variable $uri-suffix := ".xml";
declare variable $latest-tweet-uri := cts:uri-match(concat($uri-prefix,"*"))[last()];
declare variable $latest-tweet-id := if ($latest-tweet-uri)
                                     then substring-after(
                                            substring-before($latest-tweet-uri,$uri-suffix),
                                            $uri-prefix)
                                     else $initial-tweet-id;


let $content := xdmp:http-get(
                  concat("http://search.twitter.com/search.atom?q=pankaj&amp;since_id=",
                         $latest-tweet-id),
 <options xmlns="xdmp:document-get">
   <encoding>UTF-8</encoding>
 </options>)
for $entry in $content//atom:entry
let $tweet-id := tokenize($entry/atom:id, ":")[last()]
return
  ( xdmp:log(concat("Adding tweet:", $tweet-id)),
    xdmp:document-insert(
     concat($uri-prefix, $tweet-id, $uri-suffix),
     $entry,
     xdmp:default-permissions(), 
     xdmp:default-collections(), 
     10)
  )

要每30秒运行一次,您可以使用管理界面来设置计划任务(配置 - &gt;组 - &gt;默认 - &gt;计划任务)。这也是你指定运行它的数据库的地方。 (在查询控制台中,您只需使用“内容源”下拉菜单。)

替代方法:

  • 在加载时插入一个存储推文ID的元素,然后在其上使用范围索引来查找最高值。
  • <atom:published>上创建日期时间范围索引,使用该索引查找最新推文,并从<atom:id>值中提取推文ID。

我的解决方案和上述两个替代方案中的第一个不需要任何磁盘读取,因此在这方面它们更受欢迎。

答案 1 :(得分:0)

请参阅xdmp的参考手册页:http-get。 xdmp:http-get返回一系列项目。

参考手册:

  

xdmp输出中的第一个节点:http-get是响应头   来自http服务器。

     

xdmp输出中的第二个节点:http-get是来自的响应   http服务器。响应被视为文本,XML或二进制,   取决于从http服务器发送的内容类型标头。如果   node是html,标题应该表示text / html,这是返回的   默认情况下作为文本文档。文件类型由确定   mimetypes映射,您可以更改管理员中的映射   根据需要接口。如果您碰巧知道响应是XML,   即使标题没有将其指定为XML,并且想要处理它   作为XML响应,您可以将响应包装在xdmp:unquote调用中   将响应解析为XML。你也可以使用xml   选项(在xdmp:document-get命名空间中)告诉API要处理   该文档为XML。此外,如果您知道响应是HTML   文档,您可以将响应包装在xdmp:tidy调用中,这将是   将文本视为HTML,清理它并返回XHTML XML文档。

您应该检查第一项的响应类型和状态。如果它是text / xml响应,那么你可以做

for $i in $content[2]//entry

要每隔30秒运行一次,您可以使用计划任务。如果您只想存储新文档,您可以通过Twitter为每条推文提供的唯一Twitter URL / ID来存储每个文档。您还可以将最后一个'id'存储在文档中的数据库中,然后将其解除并在每次运行fetcher时更新它。