1

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

  1. 当使用函数点击此网址“ http://search.twitter.com/search.atom?q=pankaj&since_id=1212121xdmp:http-get ”时,我得到以下 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在 URL 的字段中附加最后一个条目的 id。

我正在尝试关注但遇到一些错误,我也不知道在哪里提供数据库名称以及如何附加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)
4

2 回答 2

3

一个错误可能是对未转义的 & 号的抱怨,在 XQuery(如 XML)中需要使用&amp;.

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

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

要更新 since_id 值,您有多种选择。不幸的是,来自 Twitter 的 XML 不包含原始推文 ID 作为其自己的元素或属性值,这意味着如果不先在插入时修改文档(包括此类一个字段)。但是我们可以利用我们在 URI 中使用推文 ID 的事实。启用 URI 词典(管理 UI 中的全局数据库选项)将允许您调用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 秒运行一次,您可以使用管理 UI 设置计划任务(配置 -> 组 -> 默认 -> 计划任务)。这也是您指定要在哪个数据库上运行它的地方。(在查询控制台中,您只需使用“内容源”下拉菜单。)

替代方法:

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

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

于 2012-04-15T22:03:37.110 回答
0

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

从参考手册:

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

xdmp:http-get 输出中的第二个节点是来自 http 服务器的响应。根据从 http 服务器发送的内容类型标头,响应被视为文本、XML 或二进制。如果节点是html,header应该指明text/html,默认是作为文本文档返回的。文档类型由 mimetypes 映射决定,您可以根据需要在管理界面中更改映射。如果您碰巧知道响应是 XML,即使标头没有将其指定为 XML,并且希望将响应作为 XML 处理,您可以将响应包装在 xdmp:unquote 调用中以将响应解析为 XML。您还可以使用 xml 选项(在 xdmp:document-get 命名空间中)告诉 API 将文档视为 XML。此外,如果您知道响应是 HTML 文档,

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

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

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

于 2012-04-15T21:32:24.673 回答