Skip to content

Instantly share code, notes, and snippets.

@chetanmeh
Created March 5, 2015 18:14
Show Gist options
  • Save chetanmeh/c1ccc4fa588ed1af467b to your computer and use it in GitHub Desktop.
Save chetanmeh/c1ccc4fa588ed1af467b to your computer and use it in GitHub Desktop.
Oak Lucene Index Example
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.jackrabbit.oak.jcr;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexProvider;
import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.fail;
public class LuceneJcr {
private final Logger log = LoggerFactory.getLogger(getClass());
private NodeStore nodeStore;
private Repository repository;
public void initNodeStore() throws IOException {
FileStore fileStore = FileStore.newFileStore(new File("target/"+System.currentTimeMillis())).create();
nodeStore = new SegmentNodeStore(fileStore);
}
public void initRepository() {
LuceneIndexProvider provider = new LuceneIndexProvider();
Jcr jcr = new Jcr(nodeStore)
.withAsyncIndexing()
.with(new LuceneIndexEditorProvider())
.with((QueryIndexProvider) provider)
.with((Observer) provider)
.withAsyncIndexing();
repository = jcr.createRepository();
log.info("Repository initialized");
}
public void createLuceneIndex() throws RepositoryException {
Session session = createAdminSession();
Node lucene = JcrUtils.getOrCreateByPath("/oak:index/lucene", "oak:Unstructured",
"oak:QueryIndexDefinition", session, false);
lucene.setProperty("compatVersion", 2);
lucene.setProperty("type", "lucene");
lucene.setProperty("async", "async");
Node rules = lucene.addNode("indexRules", "nt:unstructured");
Node allProps = rules.addNode("nt:base")
.addNode("properties", "nt:unstructured")
.addNode("allProps", "oak:Unstructured");
allProps.setProperty("name", ".*");
allProps.setProperty("isRegexp", true);
allProps.setProperty("nodeScopeIndex", true);
session.save();
session.logout();
log.info("Lucene index created");
}
private void createTestData() throws RepositoryException {
Session session = createAdminSession();
Node test = session.getRootNode().addNode("test");
test.setProperty("name", "torgeir");
session.save();
session.logout();
log.info("Testdata created");
}
private void performQuery() throws RepositoryException, InterruptedException {
final Session session = createAdminSession();
TimeUnit.SECONDS.sleep(5);
log.info("Going to perform query");
QueryManager qm =session.getWorkspace().getQueryManager();
final Query q = qm.createQuery("select * from [nt:base] where " +
"contains(*,'torgeir')", Query.JCR_SQL2);
new RetryLoop(new RetryLoop.Condition() {
@Override
public String getDescription() {
return "Full text query";
}
@Override
public boolean isTrue() throws Exception {
QueryResult r = q.execute();
return r.getNodes().hasNext();
}
}, 105, 200);
System.out.println(q.execute().getNodes().next());
}
private Session createAdminSession() throws RepositoryException {
return repository.login(getAdminCredentials());
}
private SimpleCredentials getAdminCredentials() {
return new SimpleCredentials("admin", "admin".toCharArray());
}
public static void main(String[] args) throws Exception {
LuceneJcr test = new LuceneJcr();
test.setUp();
}
private void setUp() throws Exception {
initNodeStore();
initRepository();
createLuceneIndex();
createTestData();
performQuery();
}
private static class RetryLoop {
private final long timeout;
static public interface Condition {
/**
* Used in failure messages to describe what was expected
*/
String getDescription();
/**
* If true we stop retrying. The RetryLoop retries on AssertionError,
* so if tests fail in this method they are not reported as
* failures but retried.
*/
boolean isTrue() throws Exception;
}
public RetryLoop(Condition c, int timeoutSeconds, int intervalBetweenTriesMsec) {
timeout = System.currentTimeMillis() + timeoutSeconds * 1000L;
while (System.currentTimeMillis() < timeout) {
try {
if (c.isTrue()) {
return;
}
} catch (AssertionError ae) {
// Retry JUnit tests failing in the condition as well
reportException(ae);
} catch (Exception e) {
reportException(e);
}
try {
Thread.sleep(intervalBetweenTriesMsec);
} catch (InterruptedException ignore) {
}
}
onTimeout();
fail("RetryLoop failed, condition is false after " + timeoutSeconds + " seconds: "
+ c.getDescription());
}
/**
* Can be overridden to report Exceptions that happen in the retry loop
*/
protected void reportException(Throwable t) {
}
/**
* Called if the loop times out without success, just before failing
*/
protected void onTimeout() {
}
}
}
@venkky
Copy link

venkky commented Sep 8, 2015

Complete log:

18:26:21,203 INFO [org.apache.jackrabbit.oak.plugins.segment.file.FileStore](default task-6) TarMK opened: target\1441716981196 (mmap=false)
18:26:21,370 INFO [org.apache.jackrabbit.oak.plugins.index.IndexUpdate](default task-6) Found a new index node [reference]. Reindexing would be requested
18:26:21,370 INFO [org.apache.jackrabbit.oak.plugins.index.IndexUpdate](default task-6) Reindexing would be performed for following indexes [/oak:index/uuid, /oak:index/reference, /oak:index/nodetype]
18:26:21,402 INFO [org.apache.jackrabbit.oak.plugins.index.IndexUpdate](default task-6) Indexing report
- /oak:index/uuid_(0)
- /oak:index/reference_(0)
- /oak:index/nodetype*(1153)

18:26:21,453 INFO [org.apache.jackrabbit.oak.plugins.index.IndexUpdate](default task-6) Reindexing would be performed for following indexes [/oak:index/principalName, /oak:index/acPrincipalName, /oak:index/authorizableId]
18:26:21,461 INFO [org.apache.jackrabbit.oak.plugins.index.IndexUpdate](default task-6) Indexing report
- /oak:index/principalName_(2)
- /oak:index/acPrincipalName_(0)
- /oak:index/authorizableId*(2)

18:26:21,465 INFO [org.apache.jackrabbit.oak.jcr.LuceneJcr](default task-6) Repository initialized
18:26:21,479 INFO [org.apache.jackrabbit.oak.jcr.LuceneJcr](default task-6) Lucene index created
18:26:21,493 INFO [org.apache.jackrabbit.oak.jcr.LuceneJcr](default task-6) Testdata created
18:26:26,440 INFO org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate Initial async index update
18:26:26,445 INFO org.apache.jackrabbit.oak.plugins.index.IndexUpdate Found a new index node [lucene]. Reindexing would be requested
18:26:56,577 INFO [org.apache.jackrabbit.oak.jcr.LuceneJcr](default task-6) Going to perform query
18:27:03,083 WARN [org.apache.jackrabbit.oak.spi.query.Cursors$TraversingCursor](default task-6) Traversed 1000 nodes with filter Filter(query=select * from [nt:base] where contains(,'torgeir') fullText="torgeir", path=); consider creating an index or changing the query
18:27:10,833 WARN [org.apache.jackrabbit.oak.spi.query.Cursors$TraversingCursor](default task-6) Traversed 1000 nodes with filter Filter(query=select * from [nt:base] where contains(,'torgeir') fullText="torgeir", path=); consider creating an index or changing the query
18:27:11,143 INFO [stdout](default task-6) Node[NodeDelegate{tree=/test: { jcr:primaryType = nt:unstructured, name = torgeir}}]

@Clay-Ferguson
Copy link

There is an updated example here from the meta64 project which does work:

OakRepository.java in meta64

@cesar-oyarzun-m
Copy link

@Clay-Ferguson do you know how to enable nrt, I can't find any documentation to do it by code only with the GUI

@vivekCrest
Copy link

There is an updated example here from the meta64 project which does work:

OakRepository.java in meta64

@Clay-Ferguson seems link is broken(404). Can you please provide example code?

@Nikitahghag
Copy link

@Clay-Ferguson can you please provide working updated example code?

@wliant
Copy link

wliant commented Jan 15, 2020

Anyone have working example of this?

@vivekCrest
Copy link

@chetanmeh, Thanks for the code, tried running the example facing following issue, could you please help getting rid of warnings,
"Traversed 1000 nodes with filter Filter, consider creating an index or changing the query" Thanks in advance..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment