简体   繁体   中英

Multiple contains() based on tokenised string

I want to match results from several partial terms search in a XQuery function

  • "joh do" matches "john doe"
  • "do jo" also matches "john doe"
  • etc.

With contains(), only "john do" or "joh" would match results.

$item[contains(., "john do")]

I'd like to do so...

$item[contains(., "joh") and contains(., "do")]

...no matter how many terms are in the search string.

I'm trying to use tokenize(), then a loop on it to create what I want

let $search := "john do"
let $terms := fn:tokenize($search, '\s')  
let $query := string-join(
    (for $t in $terms
     return 
       concat('contains(.,"', $t, '")')
     ), ' and '
)
return $query

The result of that loop is exactly as I expected it to be, but it has no effect on the XPATH query, as it were just text (and obviously concat() produce just text)

$item[$query] 

Did I miss something ? Is any function better than concat() for that example ?

Thanks for any help !

Your approach is simply not a good idea. You could do it that way, but I would strongly recommend you don't. What you are trying to do is construct a XPath/XQuery expression to evaluate it, ie you create your code. This is usually not a good idea.

Instead, you can check the condition in a for loop instead of creating this query. Even better, XQuery and XPath (but only XPath 2.0) have quantified expression , which fit perfectly for your use case:

for $item in $items
let $search := "john do"
let $terms := fn:tokenize($item, '\s')
where every $term in $terms satisfies contains($search, $term)
return $item

This is hopefully easy to grasp, because it is very close to natural language: Every term has to satisfy a certain condition (in your case a contains() )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM