Marklogic搜索选项以限制搜索JSON嵌套属性

时间:2016-01-20 19:58:21

标签: marklogic

我有一个具有以下结构的json

{"scientist":{
         "username": "XXX",
         "name":"XXXX"
          ...
    },
    "registrar":{
      "username": "YYY",
         "name":"aaaaa"
          ...
    }
   }

我想限制搜索在上面的json中搜索嵌套属性,例如: - 想要搜索"注册商/用户名" ..我试图使用搜索-constraint&# 34;容器" ..但无法进行搜索..以下是我的代码,它似乎不起作用..

嵌套的json字段搜索是否还有其他机制?

```

let $search := "(username:WHITEMK) AND (concept.registrar: )"

let $options := 
  <options xmlns="http://marklogic.com/appservices/search">
    <constraint name="concept.registrar">
      <container>
        <json-property>registrar</json-property>
      </container>
    </constraint>
    <constraint name="username">
      <value>
        <json-property>username</json-property>
        <term-option>case-insensitive</term-option>
        <term-option>wildcarded</term-option>
      </value>
    </constraint>
    <return-facets>false</return-facets>
    <return-values>false</return-values>
    <return-constraints>false</return-constraints>
    <return-frequencies>false</return-frequencies>
    <return-qtext>false</return-qtext>
    <search-option>unfiltered</search-option>
    <search-option>unfaceted</search-option>
    <search-option>format-json</search-option>
    <search-option>score-simple</search-option>
  </options>

let $start := 1
let $page-length :=10000

return search:search($search, $options, $start, $page-length)

```

谢谢, 拉维

2 个答案:

答案 0 :(得分:1)

正如今天在讨论列表中所指出的那样,如果您在包含约束之前为容器添加前缀,它应该可以工作,如:

from Tkinter import *

class myapp:
    def __init__(self, parent):
        self.row=0
        for val in ["A", "B", "C"]:
            print val
            lb = Label(top, text=val)
            lb.grid(row=self.row, column=1)
            self.row += 1

        submit_button = Button(top, text="Submit", fg="White", bg="#0094FF", 
                                font=("Grobold", 10), command = self.callfunc)
        submit_button.grid(row=100, column=1)

    def callfunc(self):
        for heading in ["Title", "Author", "Body"]:
            self.row += 1
            L1 = Label(top, text=heading)
            L1.grid(row=self.row, column=0)
            E1 = Entry(top, bd =5)
            E1.grid(row=self.row, column=1)

top = Tk()
top.title("App")
app = myapp(top)
top.mainloop()

作为脚注,当您尝试了解查询文本的解析方式时,有时更容易使用搜索:parse()。

您在短期内找到了解决方法,这很好。我希望这有助于长期解决方案。

答案 1 :(得分:0)

我能够在不添加嵌套字段的情况下获得更通用的版本是通过构建自定义搜索选项来解析嵌套的JSON属性并使用cts构建搜索查询:json-property-scope-query ..
例如:我们假设你要搜索一些3级嵌套属性

let $search := "(concept:orfs.aminoAcids.predictedMatureSeqs.domains.heavyChainIsoType:igg1)"

使用自定义解析器,我能够将其转换为以下

<cts:json-property-scope-query xmlns:cts="http://marklogic.com/cts">
<cts:property>orfs</cts:property>
<cts:json-property-scope-query>
<cts:property>aminoAcids</cts:property>
<cts:json-property-scope-query>
<cts:property>predictedMatureSeqs</cts:property>
<cts:json-property-scope-query>
<cts:property>domains</cts:property>
<cts:json-property-scope-query>
<cts:property>heavyChainIsoType</cts:property>
<cts:word-query>
<cts:text xml:lang="en">igg1</cts:text>
<cts:option>case-insensitive</cts:option>
<cts:option>punctuation-insensitive</cts:option>
<cts:option>whitespace-insensitive</cts:option>
<cts:option>wildcarded</cts:option>
</cts:word-query>
</cts:json-property-scope-query>
</cts:json-property-scope-query>
</cts:json-property-scope-query>
</cts:json-property-scope-query>
</cts:json-property-scope-query>

如果有兴趣,以下是自定义解析器的代码

xquery version "1.0-ml";
module namespace gbrsso="http://marklogic.com/gbrs/modules";
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
(:
   This module tries to build a custom constraint.. and takes into account the nested query as well
   for eg: Concept:registrar.username:mamidrx
:)

(: This is parse function which is invoked my marklogic when it sees the custom constraing :)
declare function gbrsso:parse($constraint-qtext as xs:string, $right as schema-element(cts:query)) as schema-element(cts:query){
 let $log := xdmp:log("Constraint-qtext : " || $constraint-qtext)
 let $log := xdmp:log("$right : " || fn:string($right//cts:text/text()))
 let $queryText := fn:string($right//cts:text/text())
 let $qparts := fn:tokenize($right//cts:text/text(), ":")
 let $queryText := $qparts[last()]
 let $log := xdmp:log("$queryText : " || $queryText)

  let $qpartsCnt := fn:count($qparts)

  let $query :=
      if(fn:count($qparts) = 1) then
        <root>{
          cts:word-query($queryText, ("case-insensitive", "wildcarded", "punctuation-insensitive", "whitespace-insensitive"))
          }</root>/*
      else 
        <root>{
          let $qparts := fn:tokenize($qparts[1],"\.") 
          let $endPart := $qparts[last()]
          (: remove the last part in sequence as we need to create word query with it :)
          let $qparts := fn:remove($qparts, fn:count($qparts))
          let $queryExp :=
            if(fn:count($qparts) = 0) then (: checks if it is nested... :)
               cts:json-property-scope-query($endPart, cts:word-query($queryText, ("case-insensitive", "wildcarded", "punctuation-insensitive", "whitespace-insensitive")))
            else
              let $xy := cts:json-property-scope-query($endPart, cts:word-query($queryText, ("case-insensitive", "wildcarded", "punctuation-insensitive", "whitespace-insensitive")))
              return gbrsso:buildQuery($xy, $qparts)

          return $queryExp
        }</root>/*

  return $query

};