1

对于我们存储在 MarkLogic 中的每个 XML,我们将计算值存储在文档的关联属性中。这些值之一是可能很大的十进制值。这导致了异常,因为 Marklogic Java API 正在以 MarkLogic 服务器不喜欢的方式格式化它发送到 MarkLogic 服务器的 XML 中的数字。

我们在存储在属性中的“TotalObligatedAmount”元素上设置了范围元素索引:

下面的 Java 代码重现了我们看到的问题:

import java.nio.charset.StandardCharsets;
 
import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
 
import com.marklogic.client.DatabaseClient;
import com.marklogic.client.document.XMLDocumentManager;
import com.marklogic.client.io.DOMHandle;
import com.marklogic.client.io.DocumentMetadataHandle;
 
@Component
public class LoadTester {
 
  private final XMLDocumentManager mgr;
  
  public LoadTester(DatabaseClient client) {
    this.mgr = client.newXMLDocumentManager();
  }
 
  public void loadTest() throws Exception {
    String uri = "testDocument.xml";
    DOMHandle handle = new DOMHandle();
    String xml = "<test><value>Hello World</value></test>";
    Document doc = handle.getFactory().newDocumentBuilder()
                   .parse(IOUtils.toInputStream(xml, StandardCharsets.UTF_8));
    DocumentMetadataHandle metadataHandle = new DocumentMetadataHandle();
    metadataHandle.withProperty("TotalObligatedAmount",Double.valueOf(18912626.00));
    handle.set(doc);
    mgr.write(mgr.newDescriptor(uri), metadataHandle, handle);
  }
}

这会导致以下异常:

Exception in thread "main" com.marklogic.client.FailedRequestException: Local message: write failed: Bad Request. Server Message: XDMP-RANGEINDEX: Range index error: decimal xdmp:document-properties("testDocument.xml")/prop:properties/TotalObligatedAmount: XDMP-LEXVAL: Invalid lexical value "1.8912626E7"
    at com.marklogic.client.impl.OkHttpServices.putPostDocumentImpl(OkHttpServices.java:1697)
    at com.marklogic.client.impl.OkHttpServices.putDocument(OkHttpServices.java:1344)
    at com.marklogic.client.impl.DocumentManagerImpl.write(DocumentManagerImpl.java:940)
    at com.marklogic.client.impl.DocumentManagerImpl.write(DocumentManagerImpl.java:888)
    at com.marklogic.client.impl.DocumentManagerImpl.write(DocumentManagerImpl.java:827)

Java API 正在生成并发送到服务器的属性数据 XML 是:

<?xml version='1.0' encoding='utf-8'?>
<rapi:metadata xmlns:rapi="http://marklogic.com/rest-api"
    xmlns:prop="http://marklogic.com/xdmp/property"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <prop:properties>
        <TotalObligatedAmount xsi:type="xs:double">1.8912626E7</TotalObligatedAmount>
    </prop:properties>
</rapi:metadata> 

将属性序列化为 XML 时,十进制值 18,912,626.00 被转换为字符串 1.8912626E7,MarkLogic 服务器拒绝该字符串。

我能够单步执行代码以了解如何将双精度转换为字符串。com.marklogic.client.impl.ValueConverter进行转换并使用方法将javax.xml.bind.DatatypeConverter.printDouble()Double 转换为“1.8912626E7”字符串(最终使用 String.valueOf(doubleValue) 方法。

有谁知道我该如何解决这个问题?我需要在服务器上进行更改或配置 Java API 的方法吗?

我使用的是 5.2.0 版的 Java API 和 10.0-8.1 版的 MarkLogic 服务器。

4

1 回答 1

1

事实证明,如果您将属性添加为 BigDecimal 而不是 Double 它会正确序列化。

更改metadataHandle.withProperty("TotalObligatedAmount",Double.valueOf(18912626.00));metadataHandle.withProperty("TotalObligatedAmount",new BigDecimal(18912626.00)); 足以使代码正常工作。

于 2022-01-12T18:52:09.217 回答