Как извлечь документ из базы данных и передать его преобразованию с использованием dmsdk?

#marklogic #transformation #marklogic-8 #marklogic-9

#marklogic #преобразование #marklogic-8 #marklogic-9

Вопрос:

Мне нужно извлечь документ из базы данных и применить преобразование с использованием dmsdk. Я успешно извлек документы из базы данных, используя приведенную ниже строку кодов:

         QueryManager queryManager=client.newQueryManager();
        StructuredQueryBuilder sqb = queryManager.newStructuredQueryBuilder();
        StructuredQueryDefinition query =sqb.collection("test");
  

Он возвращает URI документов. Но мое преобразование принимает объекты json в качестве входных данных.
Мне нужно передавать объекты json вместо uri.

Мое преобразование:

 xquery version "1.0-ml";

module namespace test =
  "http://marklogic.com/rest-api/transform/deepan";

declare function test:transform(
  $context as map:map,
  $params as map:map,
  $content as document-node()
) as document-node()
{
    let $jsoncont := xdmp:from-json-string($content)

    let $inputval := "fname,lname"
    let $orig-value := map:get($jsoncont, "value")

    let $jscode := "var simple = require('/wdsUtils.sjs');
                    var content, input;
                    simple.createUri(content,input);"

    let $uri := xdmp:javascript-eval($jscode,('content',$orig-value,'input',$inputval))
    let $_ := map:put($content, "uri",$uri)
    let $_ := map:put($content, "value",$orig-value)
    return $content  

};
  

Мой код dmsdk:

     static String HOST = "localhost";
    static int PORT = 8136;
    static String USER = "admin";
    static String PASSWORD = "admin";
    private static DatabaseClient client = 
            DatabaseClientFactory.newClient(
                HOST, PORT, new DigestAuthContext(USER, PASSWORD));

    public static void loadData(String txName)
    {
        QueryManager queryManager=client.newQueryManager();
        StructuredQueryBuilder sqb = queryManager.newStructuredQueryBuilder();
        StructuredQueryDefinition query =sqb.collection("test");
        DataMovementManager dmm = client.newDataMovementManager();
        QueryBatcher batcher = dmm.newQueryBatcher(query);

        batcher.withConsistentSnapshot();
        ServerTransform txform = new ServerTransform(txName);

        ApplyTransformListener transformListener = new ApplyTransformListener()
                .withTransform(txform)
                .withApplyResult(ApplyResult.REPLACE);

        batcher.onUrisReady(transformListener)          
                .onQueryFailure( exception -> exception.printStackTrace() );

        dmm.startJob(batcher);
    }

    public static void main(String[] args) 
    {
        loadData("deepan");
    }
  

Исключение:

 01:09:10.819 [main] WARN com.marklogic.client.datamovement.ApplyTransformListener - Error: com.marklogic.client.FailedRequestException: Local message: failed to apply resource at internal/apply-transform: Bad Request. Server Message: XDMP-ARGTYPE: (err:XPTY0004) fn:doc(fn:doc("/one.json")) -- arg1 is not of type xs:string* in batch with urs ([/one.json, /three.json])
01:09:10.821 [pool-1-thread-2] DEBUG com.marklogic.client.impl.OkHttpServices - Query uris with structured query <query xmlns="http://marklogic.com/appservices/search" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:search="http://marklogic.com/appservices/search" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><collection-query><uri>test</uri></collection-query></query>
01:09:10.821 [pool-1-thread-2] DEBUG com.marklogic.client.impl.OkHttpServices - Getting internal/uris as text/uri-list
01:09:10.823 [pool-1-thread-1] DEBUG com.marklogic.client.impl.OkHttpServices - Query uris with structured query <query xmlns="http://marklogic.com/appservices/search" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:search="http://marklogic.com/appservices/search" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><collection-query><uri>test</uri></collection-query></query>
01:09:10.824 [pool-1-thread-1] DEBUG com.marklogic.client.impl.OkHttpServices - Getting internal/uris as text/uri-list
01:09:10.830 [pool-1-thread-2] DEBUG com.marklogic.client.impl.OkHttpServices - Posting internal/apply-transform
01:09:10.852 [pool-1-thread-2] WARN com.marklogic.client.datamovement.ApplyTransformListener - Error: com.marklogic.client.FailedRequestException: Local message: failed to apply resource at internal/apply-transform: Bad Request. Server Message: XDMP-ARGTYPE: (err:XPTY0004) fn:doc(fn:doc("/two.json")) -- arg1 is not of type xs:string* in batch with urs ([/two.json])
  

Комментарии:

1. Выполняется ли ваш код? Вы получаете какую-либо ошибку? Не могли бы вы опубликовать это?

2. Добавлено исключение, пожалуйста, проверьте.

3. Похоже, что где-то в вашем коде их несколько fn:doc . fn:doc(fn:doc("/two.json")) должно быть только fn:doc("/two.json") , но ваш код не содержит этого выражения. Можете ли вы выполнить поиск по этому в своем коде? Однако ваш Java-код и код преобразования выглядят нормально. Не могу обнаружить ошибку там.

Ответ №1:

xdmp:from-json-string() ожидает строку, но параметром $content для преобразования является document-node(), а не строка.

Попробуйте xdmp: из-json() вместо xdmp: из-json-string(), чтобы преобразовать узел JSON в карту, если вам нужна изменяемая структура.

Кроме того, мне интересно, необходим ли xdmp: javascript-eval(). Вы должны иметь возможность вызывать функцию из XQuery с чем-то вроде

 let $uri := xdmp:apply(
    xdmp:function(xs:QName("createUri"), "/wdsUtils.sjs"),
    $orig-value,
    $inputval)
  

Возможно, нет необходимости преобразовывать узел $ content JSON в map (который становится объектным литералом в JavaScript) в зависимости от того, что делает функция createUri().

Операции map:put() не будут работать на узле. Вместо этого рассмотрите возможность преобразования map в узел JSON с чем-то вроде

 return xdmp:to-json(map:entry("uri",$uri)=>map:with("value",$orig-value))
  

Надеюсь, это поможет,

Комментарии:

1. верните xdmp:в-json(map:entry(«uri»,$uri)=>map:with(«value»,$orig-value)) этот код фактически заменяет мое содержимое на $ uri. Я не хочу заменять содержимое, я просто хочу заменить uri содержимого любым другим при получении.

2. Если вы хотите изменить только uri, вы можете установить его в контекстной карте и вернуть исходное содержимое.