javaindexinglucenejackrabbit-oak

Lucene index: getting empty result while query


I am trying to query with Lucene index but getting the empty result and below errors in the log,

Traversal query (query without index): select [jcr:path] from [nt:base] where isdescendantnode('/test') and name='World'; consider creating an index


[async] The index update failed
org.apache.jackrabbit.oak.api.CommitFailedException: OakAsync0002: Missing index provider detected for type [counter] on index [/oak:index/counter]


I am using RDB DocumentStore and I have checked index and node are created in nodes table.i tried below code,

   @Autowired 
   NodeStore rdbNodeStore;

   //create reposiotory
   LuceneIndexProvider provider = new LuceneIndexProvider();
   ContentRepository repository = new Oak(rdbNodeStore)
                .with(new OpenSecurityProvider())
                .with(new InitialContent())
                .with((QueryIndexProvider) provider)
                .with((Observer) provider)
                .with(new LuceneIndexEditorProvider())
                .withAsyncIndexing("async", 
   5).createContentRepository();

    //login reposiotory and retrive session
    ContentSession contentSession = repository.login(null, null);
    Root root = contentSession.getLatestRoot();

    //create lucene index
      Tree index = root.getTree("/");

      Tree t = index.addChild("oak:index");

      t = t.addChild("lucene");
      t.setProperty("jcr:primaryType", "oak:QueryIndexDefinition", Type.NAME);
      t.setProperty("compatVersion", Long.valueOf(2L), Type.LONG);
      t.setProperty("type", "lucene", Type.STRING);
      t.setProperty("async", "async", Type.STRING);

      t = t.addChild("indexRules");
      t = t.addChild("nt:base");
      Tree propnode = t.addChild("properties");
      Tree t1 = propnode.addChild("name");
      t1.setProperty("name", "name");
      t1.setProperty("propertyIndex", Boolean.valueOf(true), Type.BOOLEAN);
      root.commit();

      //Create TestNode
      String h = "Hello" + System.currentTimeMillis();
      String w = "World" + System.currentTimeMillis();

      Tree test = root.getTree("/").addChild("test");
      test.addChild("a").setProperty("name", Arrays.asList(new String[] { h, w }), Type.STRINGS);
      test.addChild("b").setProperty("name", h);
      root.commit();

      //Search
      String query = "select [jcr:path] from [nt:base] where isdescendantnode('/test') and name='World' option(traversal ok)";

      List<String> paths = executeQuery(root, query, "JCR-SQL2", true, false);
      for (String path : paths) {
        System.out.println("Path=" + path);
      }

can anyone share some sample code on how to create Lucene index?


Solution

  • There are a couple of issues with what you're likely doing. First thing would the error that you're observing. Since you're using InitialContent which provisions an index with type="counter". For that you'd need to have .with(new NodeCounterEditorProvider()) while building the repository. That should avoid the error you are seeing.

    But, your code would likely still not work because lucene indexes are async (which you've correctly configured). Due to that asynchronous behavior, you can't query immediately after adding the node. I tried your code but had to add something like Thread.sleep(10*1000) before going for querying.

    As another side-note, I'd recommend that you try out IndexDefinitionBuilder to make lucene index structure. So, you could replace Tree index = root.getTree("/");

    Tree t = index.addChild("oak:index");
    
    t = t.addChild("lucene");
    t.setProperty("jcr:primaryType", "oak:QueryIndexDefinition", Type.NAME);
    t.setProperty("compatVersion", Long.valueOf(2L), Type.LONG);
    t.setProperty("type", "lucene", Type.STRING);
    t.setProperty("async", "async", Type.STRING);
    
    t = t.addChild("indexRules");
    t = t.addChild("nt:base");
    Tree propnode = t.addChild("properties");
    Tree t1 = propnode.addChild("name");
    t1.setProperty("name", "name");
    t1.setProperty("propertyIndex", Boolean.valueOf(true), Type.BOOLEAN);
    root.commit();
    

    with

    IndexDefinitionBuilder idxBuilder = new IndexDefinitionBuilder();
    idxBuilder.indexRule("nt:base").property("name").propertyIndex();
    idxBuilder.build(root.getTree("/").addChild("oak:index").addChild("lucene"));
    root.commit();
    

    The latter approach, imo, is less error prone and more redabale.