2 Replies Latest reply on Feb 16, 2015 5:37 AM by haraldk

    How to Query for shared nodes in JCR (ModeShape)?


      NOTE: This question was originally asked on StackOverflow, but has not got any attention, so I'm trying my luck here. Feel free to answer it on SO.


      I have a JCR content repository implemented in ModeShape (4.0.0.Final, later upgraded to 4.1.0.Final with same result). The structure of the repository is quite simple and looks like this:


          / (root)


                  Item 1

                  Item 2

                  Item 3








      The content is initially created and stored under /Content as [nt:unstructured] nodes with [mix:shareable] mixin. When a content item is tagged, the tag node is first created under /Tags if it's not already there, and the content node is shared/cloned to the tag node using Workspace.clone(...) as described in the JCR 2.0 spec, section 14.1, Creation of Shared Nodes.


      (I don't find this particularly elegant and I did just read this answer, about creating a tag based search system in JCR, so I realize this might not be the best/fastest/most scaleable solution. But I "inherited" this solution from developers before me, so I hope I don't have to rewrite it all...)


      Anyway, the sharing itself seems to work (I can verify that the nodes are there using the ModeShape Content Explorer web app or programatically by session.getRootNode().getNode("Tags/Foo").getNodes()). But I am not able to find any shared nodes using a query!


      My initial try (using JCR_SQL2 syntax) was:


          SELECT * FROM [nt:unstructured] AS content
              WHERE PATH(content) LIKE '/Tags/Foo/%' // ISDECENDANTNODE(content, '/Tags/Foo') gives same result
              ORDER BY NAME(content)


      The result set was to my surprise empty.


      I also tried searching in [mix:shareable] like this:


          SELECT * FROM [mix:shareable] AS content
              WHERE PATH(content) LIKE '/Tags/Foo/%' // ISDECENDANTNODE(content, '/Tags/Foo') gives same result
              ORDER BY NAME(content)


      This also returned an empty result set.


      I can see from the query:


          SELECT * FROM [nt:unstructured] AS content
              WHERE PATH(content) LIKE '/Content/%' // ISDECENDANTNODE(content, '/Content') works just as well
              ORDER BY NAME(content)


      ...that the query otherwise works, and returns the expected result (all content). It just doesn't work when searching for the shared nodes.


      How do I correctly search for shared nodes in JCR using ModeShape?

        • 1. Re: How to Query for shared nodes in JCR (ModeShape)?

          Shared nodes are really just a single node that appears in multiple places within a workspace, so it's not exactly clear what it semantically means to get multiple query results for that one shareable node. Per Section 14.16 of the JSR-283 (JCR 2.0) specification implementations are free to include shareable nodes in query results at just one or at multiple/all of those locations.


          ModeShape 2.x and 3.x always returned in query results only a single location of the shared nodes, as this was the behavior of the reference implementation and this was the feedback we got from users. When we were working on Modeshape 4.0, we tried to make it possible to return multiple results, but we ran into problems with the TCK and uncertainty about what this new expected behavior would be. Therefore, we backed off our goals and implemented query to return only one of the shared locations, as we did with 2.x and 3.x.

          1 of 1 people found this helpful
          • 2. Re: How to Query for shared nodes in JCR (ModeShape)?

            Hi Randall,


            Thanks for taking the time to answer, appreciate it. Now I at least know why it does not work. :-)


            I guess what you are referring to, is the sentence of 14.16 saying "If a query matches two or more nodes in a shared set, whether all of these nodes or just one is returned in the query result is an implementation issue." I can only interpret this to mean that I should get results from my queries. My queries does not match two ore more, but (well, at least in my head, they match) exactly one node in the shared set. However, the result sets are always empty, unless I search for nodes in their "original" location (which makes shared nodes completely useless for my case).


            I do find the current behaviour to be counter intuitive. So I hope you'll look into this again. But I of course, I have the benefit of not actually having to implement a solution that have to pass TCKs.. ;-)



            Best regards,



            Harald K