xmlxpathxqueryexist-db

XQuery maps: append value with the same key to the existing map


I have these maps (they were constructed from another query):

let $my_maps :=
    (
        map {
            "book_id": "id_1",
            "title": "Some title",
            "author": "Some author",
            "date": "Some dates"
        },
        map {
            "book_id": "id_2",
            "title": "Some title",
            "author": "Some author",
            "date": "Some dates"
        }
    )

And I have this XML file:

<book xml:id="id_1">
    <introduction>texte of introduction</introduction>
    <chapter id="1">texte of  chapter 1</chapter>
    <chapter id="2">texte of chapter 2</chapter>
    <notes>texte of notes</notes>
    <conculsion>texte of conclusion</conculsion>
</book>

What I want:

My ongoing XQuery:

let $grouped_map := 
    (
        for $id in $my_maps?book_id
        
        for $book_part in collection("path_to_my_collection")/book[@xml:id = $id]//(introduction | notes)
     
        return 
            map:merge((
                $my_maps[?book_id = $id],
                
                for $part in $book_part
                group by $xml_id := $part/ancestor::book/@xml:id
                return
                    map:entry("text", $part)
                ))
    )

return
 $grouped_map

Ongoin result:

1
map {
    "book_id": "id_1",
    "title": "Some title",
    "author": "Some author",
    "date": "Some dates",
    "text": <introduction>texte of introduction</introduction>
}
2
map {
    "book_id": "id_1",
    "title": "Some title",
    "author": "Some author",
    "date": "Some dates",
    "text": <notes>texte of notes</notes>
}

Expected result:

1
map {
    "book_id": "id_1",
    "title": "Some title",
    "author": "Some author",
    "date": "Some dates",
    "text": (<introduction>texte of introduction</introduction>, <notes>texte of notes</notes>)
}

I also tried map {'duplicates' : 'combine'}:

let $grouped_map := 
    (
        for $id in $my_maps?book_id
        
        for $book_part in collection("path_to_my_collection")/book[@xml:id = $id]//(introduction | notes)
     
        return 
            map:merge((
                $my_maps[?book_id = $id],
                map:entry("text", $book_part),
                map {'duplicates' : 'combine'}
                ))
    )

return
 $grouped_map

But the result stays the same. (By the way, I use eXsit and I didn't see in its documentation about map functions any mention of map {'duplicates' : 'combine'}, so not sure they allow this...)


Solution

  • It sounds to me as if you just want

    for $map in $my_maps
    let $books := collection("path_to_my_collection")/book[@xml:id = $map?book_id]
    return map:put($map, 'text', $books ! (.//introduction | .//notes))
    

    That would put a text item into each map of the input, the value might be an empty sequence if there are no matching books.