0

我必须将地理空间搜索功能添加到使用 search:search API 并具有全文搜索和分面搜索的现有应用程序中。我已经阅读了有关扩展搜索 API 的信息,但我现在没有时间。所以,我想我会调整我的代码,以便只做两个结果集的交集(一个由 search:search API 返回,另一个由cts:search允许cts:polygon搜索的返回)。不幸的是,交叉点严重降低了执行时间。有没有更好的方法来优化或加速下面的表达式?

$results_fts//search:result[./search:metadata/Vhe eq $geo_results//root/Vhe]

这是我的代码:

declare variable $geo_results := 
let $qr := cts:search(doc(), cts:and-query(($q-geospatial,
            cts:word-query("*", ("case-insensitive","whitespace-insensitive","wildcarded","diacritic-insensitive"))   ))   )  (:Search all * within the polygon:)
return $qr;

declare variable $results_fts := 
let $qrs := search:search($q-text, $options, xs:unsignedLong(xdmp:get-request-field("start","1")), 12000)  (:max page length to get all records:)
return $qrs;

declare variable $results := 
let $qrt := if (xdmp:get-request-field("map-code")) then 
(:intersect geospatial search with the full text search:)
                <search:response>
                  { $results_fts//search:result[./search:metadata/Vhe eq $geo_results//root/Vhe] } 
                  { $results_fts//search:facet }
                  { $results_fts//search:qtext }
                  { $results_fts//search:metrics }
                </search:response>
          else $results_fts
return $qrt;
4

4 回答 4

2

作为 Dave 好建议的脚注,另一种选择是在运行 cts:search() 之前使用 search:parse() 而不是 search:search() 将第二个搜索请求转换为 cts:query。

http://docs.marklogic.com/search:parse?q=search:parse&v=8.0&api=true

然后,将 cts:query() 生成的 search:parse() 添加到现有 cts:and-query() 内的子查询列表中并运行单个搜索。

我不清楚地理空间查询中的 cts:word-query("*") 子句在做什么,但这与要点无关。

于 2015-03-05T14:03:29.583 回答
1

Lenti,您正在运行的 XPath 谓词将每个 search:result Vhe 与每个 $geo_results Vhe 进行比较——可能需要做很多工作,具体取决于找到了多少地理结果。我认为您可能高估了扩展 Search API 所需的工作量。如果您走这条路,MarkLogic 可以为您处理优化。

您需要的是自定义约束。您只需要实现解析功能,而不是开始和结束(您需要那些用于自定义方面)。看起来您使用的是字符串查询而不是结构化查询,所以是这样的:

declare function geo:parse(
  $constraint-qtext as xs:string, 
  $right as schema-element(cts:query))
as schema-element(cts:query)
{
  (: TODO: you don't show above how you construct the geospatial query,
   : but do that here using $right//cts:text as input. 
   :)
  (: If MarkLogic complains that your geospatial query doesn't match
   : the return type, you probably need to serialize it like this: 
       return <root>{$q-geospatial}</root>/*
   :) 
};

您还可以在 Search API 选项中设置约束:

<constraint name="my-custom">
  <custom facet="false">
   <parse apply="parse" ns="..." at="..." />
  </custom>
</constraint>

... 其中 ns 是命名空间,“geo:”是上面的前缀,at 是定义解析函数的库模块的路径。

资源:

于 2015-03-05T13:52:16.477 回答
0

除了 Dave 和 Eriks 的建议之外,您还可以执行与 Erik 建议相反的操作:获取 cts:search 的 cts:query,并将其作为附加查询嵌入到 search:search 的搜索选项中。您可以在运行时重新创建 $options 。这样做可以让您利用搜索库提供的所有好处。

于 2015-03-05T14:55:37.797 回答
0

这是 Geert 和 Erik 提出的想法的一个转折点。我认为这可以最大限度地减少对现有代码的更改。

declare variable $Q-GEO :=
  cts:and-query(
    ($q-geospatial,
     (: TODO This smells funny. :)
     cts:word-query(
       "*",
       ("case-insensitive", "whitespace-insensitive", "wildcarded",
        "diacritic-insensitive")) )) ;

declare variable $Q-FT := cts:query(search:parse($q-text, $options)) ;

search:resolve(
  document { cts:and-query(($Q-GEO, $Q-FT)) }/*,
  $options,
  xs:unsignedLong(xdmp:get-request-field("start", "1")),
  (: TODO Rarely a good idea to fetch so many records :)
  12000)

我同意之前的评论,即word-query *需要12000审查。对我来说,那些看起来像是等待发生的性能问题。

于 2015-03-05T17:01:41.027 回答