2016-07-29 64 views
1

我们使用Marklogic 8.0-3,而且我们的数据库有很多包含“麦当劳”和“麦当劳”的文档。在搜索“麦当劳”或“麦当劳”时,我期望得到相同的结果。但即使我将它们设置为标点符号不敏感,它们也不会给出相同的结果。用撇号Marklogic关键字搜索

search:search("McDonalds", 
    <options xmlns="http://marklogic.com/appservices/search"> 
    <term> 
     <term-option>case-insensitive</term-option> 
     <term-option>diacritic-insensitive</term-option> 
     <term-option>punctuation-insensitive</term-option> 
    </term> 
    </options> 
) 

search:search("McDonald's", 
    <options xmlns="http://marklogic.com/appservices/search"> 
    <term> 
     <term-option>case-insensitive</term-option> 
     <term-option>diacritic-insensitive</term-option> 
     <term-option>punctuation-insensitive</term-option> 
    </term> 
    </options> 
) 

现在,第一个搜索查询返回2个结果,第二个查询返回79个结果。有什么方法可以搜索关键字并忽略撇号吗?

回答

0

您的问题与MarkLogic中词语标记的方式有关。分隔字符串的空格或标点符号会导致这些字符被解析为单独的标记。在你的问题:

xdmp:describe(cts:tokenize("McDonald's")) 
=> 
(cts:word("McDonald"), cts:punctuation("'"), cts:word("s")) 

McDonald's被视为由一个标点符号令牌分开的两个词令牌的短语。当您调用punctuation-insensitive选项时,它将忽略标点符号,但它不会加入令牌来执行此操作。例如:

cts:contains("McDonald+=?%s", cts:word-query("McDonald's", "punctuation-insensitive")) 
=> 
true 

cts:contains("McDonalds", cts:word-query("McDonald's", "punctuation-insensitive")) 
=> 
false 

如果只有这样话的数量有限,我建议使用thesaurus functions that ship with MarkLogic扩大对这些词的搜索。

它也可以create override rules for MarkLogic's tokenizer,这样你可以删除索引中的撇号;不过,您可能仍然处于搜索输入消毒的状态,并且根据您的应用程序,可能会有其他意想不到的副作用。

0

这里发生的事情:

xdmp:describe(cts:tokenize("McDonald's")) 

表明,长期被分解成

(cts:word("McDonald"), cts:punctuation("'"), cts:word("s")) 

所以我们看到,单引号是标点项,而且“S”是一个独立的字。对于数据摄取和查询,标记化发生相同。现在的问题是这两个东西是否应该匹配:

  • (CTS:字( “麦当劳”),CTS:标点符号( “' ”),CTS:字(“ S”))
  • CTS:字(“麦当劳”)

他们不这样做,你可能会猜到。标点符号在这里被忽略,但这仍然让我们试图匹配“麦当劳”,其次是“s”和“麦当劳”。我不认为有任何选项可以解决这个问题。

对于您如何解决这个问题,我有三点想法。

  1. 在数据加载时,应用信封模式。从<fast-food>McDonalds</fast-food>开始,添加<fast-food>McDonald's</fast-food>

假设你原来的文档是

<doc> 
    <fast-food>McDonalds</fast-food> 
</doc> 

你可以应用转换,使它象这个:

<envelope> 
    <meta> 
    <fast-food>McDonald's</fast-food> 
    </meta> 
    <doc> 
    <fast-food>McDonalds</fast-food> 
    </doc> 
</envelope> 

现在的“麦当劳”将在本文档匹配搜索。

  1. 使用语义来跟踪“McDonalds”和“McDonald's”是同一件事并且做运行时查询扩展(在运行时,做一个SPARQL查询来查看是否存在任何同义词为您搜索的条款;如果是这样,扩大与这些条款搜索)
  2. 使用Thesaurus functionality做运行时查询扩展