MarkLogic - 自定义搜索片段
MarkLogic - Custom Search Snippet
我正在使用 Roxy 来管理我的项目。同时使用 MarkLogic 8.0-6.1
我正在尝试提交一个 searchTerm,以及 return 一个自定义格式的 search:snippet
以下是我正在执行的完整步骤:
./../roxy/ml new test-app --server-version=8 --app-type=rest
配置我的build.properties
cd test-app/
./ml local bootstrap
现在我有了我的项目结构。
创建文件 - test-app/rest-api/ext/show-search.xqy
xquery version "1.0-ml";
module namespace ss = "http://marklogic.com/rest-api/resource/show-search";
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
import module namespace json = "http://marklogic.com/xdmp/json" at "/MarkLogic/json/json.xqy";
declare
function ss:get(
$context as map:map,
$params as map:map
) as document-node()*
{
map:put($context, "output-types", "application/json"),
map:put($context, "output-status", (200, "OK")),
let $search-term := map:get($params, "searchTerm")
let $query := search:search($search-term,
<options xmlns="http://marklogic.com/appservices/search">
<transform-results apply="raw"/>
</options>
)
return document {$query}
};
(:
:)
declare
function ss:put(
$context as map:map,
$params as map:map,
$input as document-node()*
) as document-node()?
{
map:put($context, "output-types", "application/xml"),
map:put($context, "output-status", (201, "Created")),
document { "PUT called on the ext service extension" }
};
(:
:)
declare
function ss:post(
$context as map:map,
$params as map:map,
$input as document-node()*
) as document-node()*
{
map:put($context, "output-types", "application/xml"),
map:put($context, "output-status", (201, "Created")),
document { "POST called on the ext service extension" }
};
(:
:)
declare
function ss:delete(
$context as map:map,
$params as map:map
) as document-node()?
{
map:put($context, "output-types", "application/xml"),
map:put($context, "output-status", (200, "OK")),
document { "DELETE called on the ext service extension" }
};
上面的 GET 请求使用了 transform-results apply=raw
选项,部署和运行正常(我有一些测试文档)。
但是我不想 return 整个文档,我想要 return 匹配的 json 的整个部分,无论该部分在哪个部分匹配发生(较低级别)
所以我试着自己写snipper
创建文件 - test-app/rest-api/ext/show-search-snipper.xqy
xquery version "1.0-ml";
module namespace sss = "http://marklogic.com/rest-api/resource/show-search-snipper";
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
import module namespace json = "http://marklogic.com/xdmp/json" at "/MarkLogic/json/json.xqy";
declare
function sss:my-snippet(
$result as node(),
$ctsquery as schema-element(cts:query),
$options as element(search:transform-results)?
) as element(search:snippet)
{
<search:snippet>
</search:snippet>
};
然后我将 search:search
调用更新为以下
let $query := search:search($search-term,
<options xmlns="http://marklogic.com/appservices/search">
<transform-results apply="my-snippet" ns="http://marklogic.com/rest-api/resource/show-search-snipper" at="show-search-snipper.xqy"/>
</options>
)
现在我应该拥有我需要的一切(我想)
我运行部署./ml local deploy rest
得到以下
Minty-linux test-app # ./ml local deploy rest Loading REST properties
in /opt/this-is-a-test/test-app/rest-api/config/properties.xml Loading
REST options in /opt/this-is-a-test/test-app/rest-api/config/options
Loading REST extensions from /opt/this-is-a-test/test-app/rest-api/ext
ERROR: 400 "Bad Request" ERROR: {"errorResponse":{"statusCode":400,
"status":"Bad Request", "messageCode":"RESTAPI-INVALIDCONTENT",
"message":"RESTAPI-INVALIDCONTENT: (err:FOER0000) Invalid content:
invalid show-search-snipper extension: show-search-snipper either is
not a valid module or does not provide extension functions (delete,
get, put, post) in the
http://marklogic.com/rest-api/resource/show-search-snipper
namespace"}}
所以我尝试将 show-search-snipper.xqy
文件向上移动 1 级(到 test-app/rest-api/show-search-snipper.xqy`
运行部署
部署工作没有错误
点击 URL 并收到以下内容
500 Internal Server Error
INTERNAL ERROR
RESTAPI-INVALIDREQ: (err:FOER0000) Invalid request: reason: Extension
show-search does not exist. . See the MarkLogic server error log for
further detail.
尽管我知道扩展程序已正确创建,因为它在引入自定义截图功能之前运行良好。 (应用="raw")
有没有想过如何应用我的自定义截图功能或我在部署中做错了什么?
有一种更简单的方法 -- 您可以使用 extract-document-data 搜索选项。
我设置了一些示例数据以像这样使用:
xquery version "1.0-ml";
for $i in (1 to 10)
return
xdmp:document-insert(
'/test-content-' || $i || '.json',
xdmp:unquote('{ "important": { "foo": 1, "bar": 2 }, "not-important": { "stuff": 3, "blah": 4 } }')
)
引导和部署模块后,我可以在 http://localhost:8040/v1/search. However, I can start taking more control of the search results by using stored search options. Take a look in your project at rest-api/config/options/all.xml
. They were already deployed for you when you run ml local deploy modules
, so you now can search using http://localhost:8040/v1/search?options=all. Since you're using JSON data, I took it one step further and ran with: http://localhost:8040/v1/search?format=json&options=all 获得搜索结果。
我将此添加到 rest-api/config/options/all.xml
:
<extract-document-data selected="include">
<extract-path>/important</extract-path>
</extract-document-data>
这会告诉搜索选项将指定路径包含在所有搜索结果中。部署并再次 运行 搜索后,结果如下所示:
{
"index":1,
"uri":"/test-content-6.json",
"path":"fn:doc(\"/test-content-6.json\")",
"score":0,
"confidence":0,
"fitness":0,
"href":"/v1/documents?uri=%2Ftest-content-6.json",
"mimetype":"application/json",
"format":"json",
"matches":[{"path":"fn:doc(\"/test-content-6.json\")/object-node()", "match-text":[]}],
"extracted":{
"kind":"array",
"content":[
{"important":{"foo":1, "bar":2}}
]
}
},
注意最后的 "extracted" 部分——我得到 "important" JSON 属性,如选项中指定的。
有关您可以设置以控制搜索的选项的完整列表,请参阅 Query Options Reference appendix。
您是否决定继续使用自定义代码片段:
看起来 Roxy 正试图将您的代码片段模块视为资源扩展,但事实并非如此。您的代码片段应该只是模块数据库中的普通模块。
IDK 如何配置 Roxy,不幸的是,但您的目标是让 Roxy 使用 PUT /v1/ext/directories/asset
或直接插入 (`PUT /v1/documents) 安装它模块数据库参见 http://docs.marklogic.com/REST/PUT/v1/ext/[directories]/[asset]。
假设 Roxy 使用 /ext,那么您的代码片段的路径将不会是您在选项中的不合格路径。这将是一个以 /ext/ 为根的绝对路径。参见 http://docs.marklogic.com/guide/rest-dev/search#id_72390。
我正在使用 Roxy 来管理我的项目。同时使用 MarkLogic 8.0-6.1
我正在尝试提交一个 searchTerm,以及 return 一个自定义格式的 search:snippet
以下是我正在执行的完整步骤:
./../roxy/ml new test-app --server-version=8 --app-type=rest
配置我的build.properties
cd test-app/
./ml local bootstrap
现在我有了我的项目结构。
创建文件 - test-app/rest-api/ext/show-search.xqy
xquery version "1.0-ml";
module namespace ss = "http://marklogic.com/rest-api/resource/show-search";
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
import module namespace json = "http://marklogic.com/xdmp/json" at "/MarkLogic/json/json.xqy";
declare
function ss:get(
$context as map:map,
$params as map:map
) as document-node()*
{
map:put($context, "output-types", "application/json"),
map:put($context, "output-status", (200, "OK")),
let $search-term := map:get($params, "searchTerm")
let $query := search:search($search-term,
<options xmlns="http://marklogic.com/appservices/search">
<transform-results apply="raw"/>
</options>
)
return document {$query}
};
(:
:)
declare
function ss:put(
$context as map:map,
$params as map:map,
$input as document-node()*
) as document-node()?
{
map:put($context, "output-types", "application/xml"),
map:put($context, "output-status", (201, "Created")),
document { "PUT called on the ext service extension" }
};
(:
:)
declare
function ss:post(
$context as map:map,
$params as map:map,
$input as document-node()*
) as document-node()*
{
map:put($context, "output-types", "application/xml"),
map:put($context, "output-status", (201, "Created")),
document { "POST called on the ext service extension" }
};
(:
:)
declare
function ss:delete(
$context as map:map,
$params as map:map
) as document-node()?
{
map:put($context, "output-types", "application/xml"),
map:put($context, "output-status", (200, "OK")),
document { "DELETE called on the ext service extension" }
};
上面的 GET 请求使用了 transform-results apply=raw
选项,部署和运行正常(我有一些测试文档)。
但是我不想 return 整个文档,我想要 return 匹配的 json 的整个部分,无论该部分在哪个部分匹配发生(较低级别)
所以我试着自己写snipper
创建文件 - test-app/rest-api/ext/show-search-snipper.xqy
xquery version "1.0-ml";
module namespace sss = "http://marklogic.com/rest-api/resource/show-search-snipper";
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
import module namespace json = "http://marklogic.com/xdmp/json" at "/MarkLogic/json/json.xqy";
declare
function sss:my-snippet(
$result as node(),
$ctsquery as schema-element(cts:query),
$options as element(search:transform-results)?
) as element(search:snippet)
{
<search:snippet>
</search:snippet>
};
然后我将 search:search
调用更新为以下
let $query := search:search($search-term,
<options xmlns="http://marklogic.com/appservices/search">
<transform-results apply="my-snippet" ns="http://marklogic.com/rest-api/resource/show-search-snipper" at="show-search-snipper.xqy"/>
</options>
)
现在我应该拥有我需要的一切(我想)
我运行部署./ml local deploy rest
得到以下
Minty-linux test-app # ./ml local deploy rest Loading REST properties in /opt/this-is-a-test/test-app/rest-api/config/properties.xml Loading REST options in /opt/this-is-a-test/test-app/rest-api/config/options
Loading REST extensions from /opt/this-is-a-test/test-app/rest-api/ext
ERROR: 400 "Bad Request" ERROR: {"errorResponse":{"statusCode":400, "status":"Bad Request", "messageCode":"RESTAPI-INVALIDCONTENT", "message":"RESTAPI-INVALIDCONTENT: (err:FOER0000) Invalid content: invalid show-search-snipper extension: show-search-snipper either is not a valid module or does not provide extension functions (delete, get, put, post) in the http://marklogic.com/rest-api/resource/show-search-snipper namespace"}}
所以我尝试将 show-search-snipper.xqy
文件向上移动 1 级(到 test-app/rest-api/show-search-snipper.xqy`
运行部署 部署工作没有错误 点击 URL 并收到以下内容
500 Internal Server Error INTERNAL ERROR RESTAPI-INVALIDREQ: (err:FOER0000) Invalid request: reason: Extension show-search does not exist. . See the MarkLogic server error log for further detail.
尽管我知道扩展程序已正确创建,因为它在引入自定义截图功能之前运行良好。 (应用="raw")
有没有想过如何应用我的自定义截图功能或我在部署中做错了什么?
有一种更简单的方法 -- 您可以使用 extract-document-data 搜索选项。
我设置了一些示例数据以像这样使用:
xquery version "1.0-ml";
for $i in (1 to 10)
return
xdmp:document-insert(
'/test-content-' || $i || '.json',
xdmp:unquote('{ "important": { "foo": 1, "bar": 2 }, "not-important": { "stuff": 3, "blah": 4 } }')
)
引导和部署模块后,我可以在 http://localhost:8040/v1/search. However, I can start taking more control of the search results by using stored search options. Take a look in your project at rest-api/config/options/all.xml
. They were already deployed for you when you run ml local deploy modules
, so you now can search using http://localhost:8040/v1/search?options=all. Since you're using JSON data, I took it one step further and ran with: http://localhost:8040/v1/search?format=json&options=all 获得搜索结果。
我将此添加到 rest-api/config/options/all.xml
:
<extract-document-data selected="include">
<extract-path>/important</extract-path>
</extract-document-data>
这会告诉搜索选项将指定路径包含在所有搜索结果中。部署并再次 运行 搜索后,结果如下所示:
{
"index":1,
"uri":"/test-content-6.json",
"path":"fn:doc(\"/test-content-6.json\")",
"score":0,
"confidence":0,
"fitness":0,
"href":"/v1/documents?uri=%2Ftest-content-6.json",
"mimetype":"application/json",
"format":"json",
"matches":[{"path":"fn:doc(\"/test-content-6.json\")/object-node()", "match-text":[]}],
"extracted":{
"kind":"array",
"content":[
{"important":{"foo":1, "bar":2}}
]
}
},
注意最后的 "extracted" 部分——我得到 "important" JSON 属性,如选项中指定的。
有关您可以设置以控制搜索的选项的完整列表,请参阅 Query Options Reference appendix。
您是否决定继续使用自定义代码片段:
看起来 Roxy 正试图将您的代码片段模块视为资源扩展,但事实并非如此。您的代码片段应该只是模块数据库中的普通模块。
IDK 如何配置 Roxy,不幸的是,但您的目标是让 Roxy 使用 PUT /v1/ext/directories/asset
或直接插入 (`PUT /v1/documents) 安装它模块数据库参见 http://docs.marklogic.com/REST/PUT/v1/ext/[directories]/[asset]。
假设 Roxy 使用 /ext,那么您的代码片段的路径将不会是您在选项中的不合格路径。这将是一个以 /ext/ 为根的绝对路径。参见 http://docs.marklogic.com/guide/rest-dev/search#id_72390。