There's more going on in the functions than just this check (which is the only 
part of the function I needed help with hopefully) and I recorded the time for 
the entire function call.  
The only difference between the two sets of times I reported is the line I 
included above the times (map:keys...).

Using exists was even slower. 

So, perhaps there's something in how I'm using it - I haven't given you the 
whole function.

Sorry if the subject was misleading, but in fact, I do want to be able to find 
a set of keys using this same technique (i.e., one of them) within another 
function.  This is just the first way I need to use it when building the entire 
map.

Thanks again,
David

-----Original Message-----
From: [email protected] 
[mailto:[email protected]] On Behalf Of Michael Blakeley
Sent: Friday, August 02, 2013 10:57 AM
To: MarkLogic Developer Discussion
Subject: Re: [MarkLogic Dev General] finding a set of keys in map

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
_______________________________________________
General mailing list
[email protected]
http://developer.marklogic.com/mailman/listinfo/general

Reply via email to