Re: [basex-talk] for-each issue on child-elements

2021-08-14 Thread Christian Grün
Hi Rob,

I’ve created an issue to track this down [1].

And I remember you have posted a similar bug in the past [2]… The challenge
was/is to find out at compile time if a function is being inlined that has
already been inlined.

Another workaround:
$context/child::* ! $context.processor(., $context.processor)

Cheers,
Christian

[1] https://github.com/BaseXdb/basex/issues/2033
[2] https://github.com/BaseXdb/basex/issues/879


On Sat, Aug 14, 2021 at 10:37 AM Rob Stapper  wrote:

> Hi Christian,
>
>
>
> I encountered this erroneous behavior while using the for-each-function on
> a set with child-elements.
>
> The evident work-around [2] workd fine.
>
> I’m using BaseX 9.6 RC2.
>
> I attached the code as attachment.
>
> Hope this helps.
>
>
>
> [1]
>
> let   $context :=
> 
>
>
>
> let   $context.processor :=
>
> function( $context   as element( )
>
> , $context.processor as function(*)
>
> )as map(*)
>
> { map { $context => name() : $context/child::*
>
>  => for-each( $context.processor( ?
>
> ,
> $context.processor
>
> )
>
> )
>
>   }
>
> }
>
> return$context
>
>   => $context.processor( $context.processor
>
>)
>
> [2]
>
> let   $context :=
> 
>
>
>
> let   $context.processor :=
>
> function( $context   as element( )
>
> , $context.processor as function(*)
>
> )as map(*)
>
> { map { $context => name() : $context/child::*
>
>  => for-each( function( $child as
> element( )
>
>   )
>
>   { $child
>
> =>
> $context.processor( $context.processor
>
>
> )
>
>   }
>
> )
>
>   }
>
> }
>
> return$context
>
>   => $context.processor( $context.processor
>
>)
>
>
>
> Rob
>
>
>
> Sent from Mail  for
> Windows
>
>
>
>
> 
>  Virus-free.
> www.avast.com
> 
> <#m_3245395734233364133_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
>


Re: [basex-talk] Can XQuery return unique values present across multiple databases?

2021-08-14 Thread Marco Lettere
Welcome Tamara and yes, Gerrit is completely right about BaseX + RestXQ. 
Most of the time you don't need more! :-D


M.

On 13/08/21 22:07, Imsieke, Gerrit, le-tex wrote:

Tamara! Welcome to another proselyte in the Church of Xquery.

This church is open to people from all walks of life, for example, 
from XSLT or XForms backgrounds.


But not from PHP.

Just kidding, everyone is free to use the tools and languages they got 
accustomed to (until they are made aware of the X stack, that is).


Do more with BaseX and RESTXQ, it is quite rewarding! The community is 
nice, inclusive, and welcoming.


Gerrit

On 13.08.2021 20:50, Tamara Marnell wrote:
Thank you, Martin! I'm new to XQuery and didn't know about 
higher-order functions like fold-left. With a little tweaking, this 
is perfect for my application:


declare variable $d as xs:string external;
declare variable $f as xs:string external;
declare function local:get_eads($facet as xs:string, $db_ids as 
item()+) as item()* {

   let $split := tokenize($facet, ':')
   return db:open('facet-' || $split[1])/terms/term[@text=$split[2] 
and @db=$db_ids]/ead

};
let $db_ids := tokenize($d, '\|')
let $facets := tokenize($f, '\|')
let $eads :=
   fold-left(
     $facets,
     local:get_eads(head($facets), $db_ids),
     function($all_eads, $facet) {
       let $facet_eads := local:get_eads($facet, $db_ids)
       let $eads_in_both := distinct-values($all_eads[.=$facet_eads])
       return $eads_in_both
     }
   )
return {
   for $ead in $eads
     return {$ead}
}

On Thu, Aug 12, 2021 at 11:27 PM Martin Honnen > wrote:



    Am 13.08.2021 um 00:12 schrieb Tamara Marnell:

    Short question: Is it possible to write an XQuery FLWOR statement
    that can return a set of unique values present across multiple
    databases?

    Long question: Our new website in development displays EAD finding
    aids stored across 45 databases in BaseX. I've built "facet"
    databases that index terms in the EADs from controlled
    vocabularies like subjects, places, personal names, etc. The
    indexes follow this structure, where each EAD node contains a
    unique identifier:

    
      
        12345
        67890
      
      
        abcde
      
      {etc.}
    

    In the search interface, users can select multiple facets to apply
    to one search. For example, they could browse database 12 for EADs
    with the subject "Literature" /and/ the place "Oregon," etc.

    I currently use the REST server to run an XQuery file that loops
    through each selected facet and prints /all/ EAD IDs for each
    submitted term and database. Then after results are returned, I
    use PHP to count occurences of each EAD and print them only if the
    total count matches the count of facets used.

    declare variable $d as xs:string external;
    declare variable $f as xs:string external;
    let $db_ids := tokenize($d, '\|')
    return {
    for $facet in tokenize($f, '\|')
      let $split := tokenize($facet, ':')
      let $facet_type := $split[1]
      let $facet_term := $split[2]
      let $facet_db := 'facet-' || $facet_type
      return {
        for $ead in db:open($facet_db)/terms/term[@text=$facet_term
    and @db=$db_ids]/ead
          return $ead
      }
    }

    So in the hypothetical example above, I'd pass "12" as d (or
    multiple selected databases separated by bars) and
    "subject:Literature|geogname:Oregon" as f, and I'd get back a
    document like:

    
      
        12345
        67890
      
      
        12345
      
    

    The count of "12345" will equal the count of the user's selected
    facets, so that result will be printed, but 67890 will not.

    Is there a more efficient way to do this? I'd prefer the XQuery to
    return only the EADs that meet all criteria, so only 12345 would
    be returned because it's in facet-subject under Literature /and/
    in facet-geogname under "Oregon," and then I don't have to do any
    post-processing.



    I think you can use fold-left to reduce the found eas while
    selecting them:



    let $db_ids := tokenize($d, '\|')
    return
     {
     let $facet-maps :=
   fold-left(
     for $facet in tokenize($f, '\|')
   let $split := tokenize($facet, ':')
   let $facet_type := $split[1]
   let $facet_term := $split[2]
   let $facet_db := 'facet-' || $facet_type
     return
   map:merge(
   for $ead in
    db:open($facet_db)/terms/term[@text=$facet_term and @db=$db_ids]/ead
   return map:entry(string($ead), map { 'node' :
    $ead, 'type' : $facet_type, 'term' : $facet_term })
   ,
   map { 'duplicates' : 'combine' }
   )
    ,
    map{},
    function($ams, $m) {
    for $m1 in $ams
    

[basex-talk] for-each issue on child-elements

2021-08-14 Thread Rob Stapper
Hi Christian,

I encountered this erroneous behavior while using the for-each-function on a 
set with child-elements.
The evident work-around [2] workd fine.
I’m using BaseX 9.6 RC2.
I attached the code as attachment.
Hope this helps.

[1]
let   $context := 

let   $context.processor :=
function( $context   as element( )
, $context.processor as function(*)
)as map(*)
{ map { $context => name() : $context/child::*
 => for-each( $context.processor( ?
, 
$context.processor
)
)
  }
}
return$context
  => $context.processor( $context.processor
   )
[2]
let   $context := 

let   $context.processor :=
function( $context   as element( )
, $context.processor as function(*)
)as map(*)
{ map { $context => name() : $context/child::*
 => for-each( function( $child as element( )
  )
  { $child
=> 
$context.processor( $context.processor

 )
  }
)
  }
}
return$context
  => $context.processor( $context.processor
   )

Rob

Sent from Mail for Windows



--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
<>