There's something wrong if either of those expressions takes 20-sec with 80
keys.
But I think I misunderstood the output you wanted. The SMO will just return
true or false, which is great if that's all you want. I was looking at the
subject "finding a set of keys in map", which is what that predicate does. But
if you only want a boolean result:
exists(map:keys($map)[contains(., $v)])
That might help a bit, since exists() should be able to stop as soon as it
finds a match. The SMO expression with op:equals probably does that too. With
10^6 keys I find that they perform about the same, and I can see the
short-circuit happening in the profiler.
declare variable $map := map:map() ;
declare variable $v := 'ab' ;
declare variable $start := () ;
(1 to 1000000) ! xdmp:integer-to-hex(xdmp:random()) ! map:put($map, ., .),
map:count($map),
xdmp:set($start, xdmp:elapsed-time()),
exists(map:keys($map)[contains(. ,$v)]),
xdmp:elapsed-time() - $start,
xdmp:set($start, xdmp:elapsed-time()),
(map:keys($map) ! fn:contains(.,$v)) = true(),
xdmp:elapsed-time() - $start,
xdmp:elapsed-time()
=>
1000000
true
PT0.655776S
true
PT0.669854S
PT6.356527S
Most of the time is spent building the map, but SMO takes about the same amount
of time as the predicate.
-- Mike
On 2 Aug 2013, at 07:29 , "Steiner, David J. (LNG-DAY)"
<[email protected]> wrote:
> With two test run, the non-predicate seems faster, or as fast. Perhaps with
> a lot more keys, there'll be a difference...
>
> At any rate, this is great! I appreciate it very much!
>
>
> With ((map:keys($map) ! fn:contains(.,$v)) = fn:true()):
> test1 (80 keys)
> <qm:elapsed-time xmlns:qm="http://marklogic.com/xdmp/query-meters"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> PT21.34633S
> </qm:elapsed-time>
>
> test2 (16 keys)
> <qm:elapsed-time xmlns:qm="http://marklogic.com/xdmp/query-meters"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> PT0.554321S
> </qm:elapsed-time>
>
>
> With (map:keys($map)[contains(., $v)]):
> test1 (80 keys)
> <qm:elapsed-time xmlns:qm="http://marklogic.com/xdmp/query-meters"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> PT21.449702S
> </qm:elapsed-time>
>
> test2 (16 keys)
> <qm:elapsed-time xmlns:qm="http://marklogic.com/xdmp/query-meters"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> PT1.506917S
> </qm:elapsed-time>
>
> -----Original Message-----
> From: [email protected]
> [mailto:[email protected]] On Behalf Of Michael Blakeley
> Sent: Friday, August 02, 2013 9:55 AM
> To: MarkLogic Developer Discussion
> Subject: Re: [MarkLogic Dev General] finding a set of keys in map
>
> I think you'd want a predicate rather than a SMO. This is an exhaustive
> search, but it will probably be plenty fast because the map is already in
> memory anyway.
>
> map:keys($m)[contains(., $substring)]
>
> Or use a regex via fn:matches, etc. If you really need wildcards rather than
> regex, you could build a text node around each key and use cts:contains.
> That's necessary because cts:contains expects nodes - but that will be a
> little more expensive too.
>
> map:keys($m)[cts:contains(text { . }, $glob)]
>
> But if the keyset is large enough that a scan isn't practical, there may be
> other options. If you have a pretty good idea of what wildcard patterns you
> need, you might be able to change the way you build keys. For example you
> could insert wildcarded keys that map to the right keys.
>
> If you know that the keys are based on a real element that has a range index,
> you could use cts:element-value-match on that. But I think both of the
> previous approaches are likely to be faster.
>
> -- Mike
>
> On 2 Aug 2013, at 06:40 , David Lee <[email protected]> wrote:
>
>> Its not highly efficient but since maps are internally hash-maps there is no
>> wildcard indexing on them.
>> You have to manually iterate the keys.
>> This or something like it (by memory) should work
>>
>> (map:keys( $map ) ! fn:contains(.,"*wildcard")) = fn:true()
>>
>>
>>
>>
>>
>> -----------------------------------------------------------------------------
>> David Lee
>> Lead Engineer
>> MarkLogic Corporation
>> [email protected]
>> Phone: +1 812-482-5224
>> Cell: +1 812-630-7622
>> www.marklogic.com
>>
>>
>> From: [email protected]
>> [mailto:[email protected]] On Behalf Of Steiner, David
>> J. (LNG-DAY)
>> Sent: Friday, August 02, 2013 9:34 AM
>> To: MarkLogic Developer Discussion
>> Subject: [MarkLogic Dev General] finding a set of keys in map
>>
>> Is there a way to find a group of map entries by "wildcarding" a key?
>>
>> Ideally, I'd like to say: map:contains($map, "*value-to-find") and get back
>> "true" if any of my keys contain "value-to-find".
>>
>> Thanks,
>> David
>> _______________________________________________
>> General mailing list
>> [email protected]
>> http://developer.marklogic.com/mailman/listinfo/general
>
> _______________________________________________
> General mailing list
> [email protected]
> http://developer.marklogic.com/mailman/listinfo/general
> _______________________________________________
> General mailing list
> [email protected]
> http://developer.marklogic.com/mailman/listinfo/general
>
_______________________________________________
General mailing list
[email protected]
http://developer.marklogic.com/mailman/listinfo/general