Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lucene cross class queries #9855

Open
wants to merge 1 commit into
base: 3.1.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public OIndex createIndex(
|| indexDefinition.getClassName() == null
|| indexDefinition.getFields() == null
|| indexDefinition.getFields().isEmpty();
if (manualIndexesAreUsed) {
if (manualIndexesAreUsed && !"LUCENE_CROSS_CLASS".equals(algorithm)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not include the specific check for "LUCENE_CROSS_CLASS" and just leave the default check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the cross class index isn't really a manual index, it just collides with the manual index logic as it's created as a special case index. This was just replicating the logic in OCreateIndexStatement.execute, which special cases the index.
It should probably be modelled as a distinct type of index (i.e. maybe a virtual index) that has no key fields, but since the existing hack was in place I replicated it rather than extend the index SPI.

As you say, we can work around that by enabling manual indexes, but it's a bit messy either way.

OIndexAbstract.manualIndexesWarning();
} else {
checkSecurityConstraintsForIndexCreate(database, indexDefinition);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/*
* Copyright 2010-2016 OrientDB LTD (http://orientdb.com)
*
* Licensed 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 com.orientechnologies.lucene;

import static com.orientechnologies.orient.core.metadata.schema.OClass.INDEX_TYPE.FULLTEXT;

import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.lucene.engine.OLuceneCrossClassIndexEngine;
import com.orientechnologies.lucene.index.OLuceneFullTextIndex;
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.db.ODatabaseDocumentInternal;
import com.orientechnologies.orient.core.db.ODatabaseInternal;
import com.orientechnologies.orient.core.db.ODatabaseLifecycleListener;
import com.orientechnologies.orient.core.exception.OConfigurationException;
import com.orientechnologies.orient.core.index.*;
import com.orientechnologies.orient.core.index.engine.OBaseIndexEngine;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.storage.OStorage;
import com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.lucene.analysis.standard.StandardAnalyzer;

public class OLuceneCrossClassIndexFactory implements OIndexFactory, ODatabaseLifecycleListener {

public static final String LUCENE_CROSS_CLASS = "LUCENE_CROSS_CLASS";

private static final Set<String> TYPES;
private static final Set<String> ALGORITHMS;

static {
final Set<String> types = new HashSet<String>();
types.add(FULLTEXT.toString());
TYPES = Collections.unmodifiableSet(types);
}

static {
final Set<String> algorithms = new HashSet<String>();
algorithms.add(LUCENE_CROSS_CLASS);
ALGORITHMS = Collections.unmodifiableSet(algorithms);
}

public OLuceneCrossClassIndexFactory() {
this(false);
}

public OLuceneCrossClassIndexFactory(boolean manual) {
if (!manual) Orient.instance().addDbLifecycleListener(this);
}

@Override
public int getLastVersion(final String algorithm) {
return 0;
}

@Override
public Set<String> getTypes() {
return TYPES;
}

@Override
public Set<String> getAlgorithms() {
return ALGORITHMS;
}

@Override
public OIndexInternal createIndex(
String name,
OStorage storage,
String indexType,
String algorithm,
String valueContainerAlgorithm,
ODocument metadata,
int version)
throws OConfigurationException {

OAbstractPaginatedStorage paginated = (OAbstractPaginatedStorage) storage.getUnderlying();

if (metadata == null) {
metadata = new ODocument().field("analyzer", StandardAnalyzer.class.getName());
}

if (FULLTEXT.toString().equalsIgnoreCase(indexType)) {
final int binaryFormatVersion = paginated.getConfiguration().getBinaryFormatVersion();
OLuceneFullTextIndex index =
new OLuceneFullTextIndex(
name,
indexType,
algorithm,
version,
paginated,
valueContainerAlgorithm,
metadata,
binaryFormatVersion);

return index;
}

throw new OConfigurationException("Unsupported type : " + algorithm);
}

public OBaseIndexEngine createIndexEngine(
int indexId,
String algorithm,
String indexName,
Boolean durableInNonTxMode,
OStorage storage,
int version,
int apiVersion,
boolean multiValue,
Map<String, String> engineProperties) {

if (LUCENE_CROSS_CLASS.equalsIgnoreCase(algorithm)) {
return new OLuceneCrossClassIndexEngine(indexId, storage, indexName);
}
throw new OConfigurationException("Unsupported type : " + algorithm);
}

@Override
public PRIORITY getPriority() {
return PRIORITY.REGULAR;
}

@Override
public void onCreate(ODatabaseInternal db) {
createCrossClassSearchIndex(db);
}

@Override
public void onOpen(ODatabaseInternal db) {
createCrossClassSearchIndex(db);
}

@Override
public void onClose(ODatabaseInternal db) {
OLogManager.instance().debug(this, "onClose");
}

@Override
public void onDrop(final ODatabaseInternal db) {
try {
if (db.isClosed()) return;

OLogManager.instance().debug(this, "Dropping Lucene indexes...");

final ODatabaseDocumentInternal internal = (ODatabaseDocumentInternal) db;
internal.getMetadata().getIndexManagerInternal().getIndexes(internal).stream()
.filter(idx -> idx.getInternal() instanceof OLuceneCrossClassIndexEngine)
.peek(idx -> OLogManager.instance().debug(this, "deleting index " + idx.getName()))
.forEach(idx -> idx.delete());

} catch (Exception e) {
OLogManager.instance().warn(this, "Error on dropping Lucene indexes", e);
}
}

@Override
public void onLocalNodeConfigurationRequest(ODocument iConfiguration) {}

private void createCrossClassSearchIndex(ODatabaseInternal db) {
final ODatabaseDocumentInternal internal = (ODatabaseDocumentInternal) db;
final OIndexManagerAbstract indexManager = internal.getMetadata().getIndexManagerInternal();

if (!indexManager.existsIndex("CrossClassSearchIndex")) {
OLogManager.instance().info(this, "creating cross class Lucene index");

db.command("CREATE INDEX CrossClassSearchIndex FULLTEXT ENGINE LUCENE_CROSS_CLASS").close();
}
}
}
Loading