start work on more like this action

This commit is contained in:
kimchy 2010-02-27 00:52:13 +02:00
parent 1ec1716a7b
commit 284a35131c
21 changed files with 962 additions and 222 deletions

View File

@ -45,6 +45,7 @@ import org.elasticsearch.action.deletebyquery.TransportIndexDeleteByQueryAction;
import org.elasticsearch.action.deletebyquery.TransportShardDeleteByQueryAction; import org.elasticsearch.action.deletebyquery.TransportShardDeleteByQueryAction;
import org.elasticsearch.action.get.TransportGetAction; import org.elasticsearch.action.get.TransportGetAction;
import org.elasticsearch.action.index.TransportIndexAction; import org.elasticsearch.action.index.TransportIndexAction;
import org.elasticsearch.action.mlt.TransportMoreLikeThisAction;
import org.elasticsearch.action.search.TransportSearchAction; import org.elasticsearch.action.search.TransportSearchAction;
import org.elasticsearch.action.search.TransportSearchScrollAction; import org.elasticsearch.action.search.TransportSearchScrollAction;
import org.elasticsearch.action.search.type.*; import org.elasticsearch.action.search.type.*;
@ -100,5 +101,7 @@ public class TransportActionModule extends AbstractModule {
bind(TransportSearchScrollQueryThenFetchAction.class).asEagerSingleton(); bind(TransportSearchScrollQueryThenFetchAction.class).asEagerSingleton();
bind(TransportSearchScrollAction.class).asEagerSingleton(); bind(TransportSearchScrollAction.class).asEagerSingleton();
bind(TransportMoreLikeThisAction.class).asEagerSingleton();
} }
} }

View File

@ -40,6 +40,8 @@ public class TransportActions {
public static final String TERMS = "indices/terms"; public static final String TERMS = "indices/terms";
public static final String MORE_LIKE_THIS = "indices/moreLikeThis";
public static class Admin { public static class Admin {
public static class Indices { public static class Indices {

View File

@ -0,0 +1,274 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.elasticsearch.action.mlt;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.Actions;
import org.elasticsearch.util.Strings;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
public class MoreLikeThisRequest implements ActionRequest {
private String index;
private String type;
private String id;
private String[] fields;
private float percentTermsToMatch = -1;
private int minTermFrequency = -1;
private int maxQueryTerms = -1;
private String[] stopWords = null;
private int minDocFreq = -1;
private int maxDocFreq = -1;
private int minWordLen = -1;
private int maxWordLen = -1;
private Boolean boostTerms = null;
private float boostTermsFactor = -1;
private boolean threadedListener = false;
public MoreLikeThisRequest() {
}
public MoreLikeThisRequest(String index) {
this.index = index;
}
public String index() {
return index;
}
public String type() {
return type;
}
public MoreLikeThisRequest type(String type) {
this.type = type;
return this;
}
public String id() {
return id;
}
public MoreLikeThisRequest id(String id) {
this.id = id;
return this;
}
public String[] fields() {
return this.fields;
}
public MoreLikeThisRequest percentTermsToMatch(float percentTermsToMatch) {
this.percentTermsToMatch = percentTermsToMatch;
return this;
}
public float percentTermsToMatch() {
return this.percentTermsToMatch;
}
public MoreLikeThisRequest minTermFrequency(int minTermFrequency) {
this.minTermFrequency = minTermFrequency;
return this;
}
public int minTermFrequency() {
return this.minTermFrequency;
}
public MoreLikeThisRequest maxQueryTerms(int maxQueryTerms) {
this.maxQueryTerms = maxQueryTerms;
return this;
}
public int maxQueryTerms() {
return this.maxQueryTerms;
}
public MoreLikeThisRequest stopWords(String... stopWords) {
this.stopWords = stopWords;
return this;
}
public String[] stopWords() {
return this.stopWords;
}
public MoreLikeThisRequest minDocFreq(int minDocFreq) {
this.minDocFreq = minDocFreq;
return this;
}
public int minDocFreq() {
return this.minDocFreq;
}
public MoreLikeThisRequest maxDocFreq(int maxDocFreq) {
this.maxDocFreq = maxDocFreq;
return this;
}
public int maxDocFreq() {
return this.maxDocFreq;
}
public MoreLikeThisRequest minWordLen(int minWordLen) {
this.minWordLen = minWordLen;
return this;
}
public int minWordLen() {
return this.minWordLen;
}
public MoreLikeThisRequest maxWordLen(int maxWordLen) {
this.maxWordLen = maxWordLen;
return this;
}
public int maxWordLen() {
return this.maxWordLen;
}
public MoreLikeThisRequest boostTerms(boolean boostTerms) {
this.boostTerms = boostTerms;
return this;
}
public Boolean boostTerms() {
return this.boostTerms;
}
public MoreLikeThisRequest boostTermsFactor(float boostTermsFactor) {
this.boostTermsFactor = boostTermsFactor;
return this;
}
public float boostTermsFactor() {
return this.boostTermsFactor;
}
@Override public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (index == null) {
validationException = Actions.addValidationError("index is missing", validationException);
}
if (type == null) {
validationException = Actions.addValidationError("type is missing", validationException);
}
if (id == null) {
validationException = Actions.addValidationError("id is missing", validationException);
}
return validationException;
}
@Override public boolean listenerThreaded() {
return threadedListener;
}
@Override public ActionRequest listenerThreaded(boolean listenerThreaded) {
this.threadedListener = listenerThreaded;
return this;
}
@Override public void readFrom(DataInput in) throws IOException, ClassNotFoundException {
index = in.readUTF();
type = in.readUTF();
id = in.readUTF();
// no need to pass threading over the network, they are always false when coming throw a thread pool
int size = in.readInt();
if (size == 0) {
fields = Strings.EMPTY_ARRAY;
} else {
fields = new String[in.readInt()];
for (int i = 0; i < size; i++) {
fields[i] = in.readUTF();
}
}
percentTermsToMatch = in.readFloat();
minTermFrequency = in.readInt();
maxQueryTerms = in.readInt();
size = in.readInt();
if (size > 0) {
stopWords = new String[size];
for (int i = 0; i < size; i++) {
stopWords[i] = in.readUTF();
}
}
minDocFreq = in.readInt();
maxDocFreq = in.readInt();
minWordLen = in.readInt();
maxWordLen = in.readInt();
if (in.readBoolean()) {
boostTerms = in.readBoolean();
}
boostTermsFactor = in.readFloat();
}
@Override public void writeTo(DataOutput out) throws IOException {
out.writeUTF(index);
out.writeUTF(type);
out.writeUTF(id);
if (fields == null) {
out.writeInt(0);
} else {
out.writeInt(fields.length);
for (String field : fields) {
out.writeUTF(field);
}
}
out.writeFloat(percentTermsToMatch);
out.writeInt(minTermFrequency);
out.writeInt(maxQueryTerms);
if (stopWords == null) {
out.writeInt(0);
} else {
out.writeInt(stopWords.length);
for (String stopWord : stopWords) {
out.writeUTF(stopWord);
}
}
out.writeInt(minDocFreq);
out.writeInt(maxDocFreq);
out.writeInt(minWordLen);
out.writeInt(maxWordLen);
if (boostTerms == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeBoolean(boostTerms);
}
out.writeFloat(boostTermsFactor);
}
}

View File

@ -0,0 +1,195 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.elasticsearch.action.mlt;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.Term;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.TransportActions;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.TransportGetAction;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.TransportSearchAction;
import org.elasticsearch.action.support.BaseAction;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.FieldMappers;
import org.elasticsearch.index.mapper.InternalMapper;
import org.elasticsearch.index.query.json.BoolJsonQueryBuilder;
import org.elasticsearch.index.query.json.MoreLikeThisFieldJsonQueryBuilder;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.transport.BaseTransportRequestHandler;
import org.elasticsearch.transport.TransportChannel;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.util.settings.Settings;
import java.util.Set;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.index.query.json.JsonQueryBuilders.*;
import static org.elasticsearch.search.builder.SearchSourceBuilder.*;
/**
* @author kimchy (shay.banon)
*/
public class TransportMoreLikeThisAction extends BaseAction<MoreLikeThisRequest, SearchResponse> {
private final TransportSearchAction searchAction;
private final TransportGetAction getAction;
private final IndicesService indicesService;
@Inject public TransportMoreLikeThisAction(Settings settings, TransportSearchAction searchAction, TransportGetAction getAction,
IndicesService indicesService, TransportService transportService) {
super(settings);
this.searchAction = searchAction;
this.getAction = getAction;
this.indicesService = indicesService;
transportService.registerHandler(TransportActions.MORE_LIKE_THIS, new TransportHandler());
}
@Override protected void doExecute(final MoreLikeThisRequest request, final ActionListener<SearchResponse> listener) {
GetRequest getRequest = getRequest(request.index())
.type(request.type())
.id(request.id())
.listenerThreaded(false);
getAction.execute(getRequest, new ActionListener<GetResponse>() {
@Override public void onResponse(GetResponse getResponse) {
if (getResponse.empty()) {
listener.onFailure(new ElasticSearchException("document missing"));
return;
}
final BoolJsonQueryBuilder boolBuilder = boolQuery();
try {
DocumentMapper docMapper = indicesService.indexServiceSafe(request.index()).mapperService().documentMapper(request.type());
final Set<String> fields = Sets.newHashSet();
if (request.fields() != null) {
for (String field : request.fields()) {
FieldMappers fieldMappers = docMapper.mappers().smartName(field);
if (fieldMappers != null) {
fields.add(fieldMappers.mapper().names().indexName());
} else {
fields.add(field);
}
}
}
docMapper.parse(request.type(), request.id(), getResponse.source(), new DocumentMapper.ParseListenerAdapter() {
@Override public boolean beforeFieldAdded(FieldMapper fieldMapper, Fieldable field, Object parseContext) {
if (fieldMapper instanceof InternalMapper) {
return true;
}
String value = fieldMapper.valueAsString(field);
if (value == null) {
return false;
}
if (fields.isEmpty() || fields.contains(field.name())) {
addMoreLikeThis(request, boolBuilder, fieldMapper, field);
}
return false;
}
});
// exclude myself
Term uidTerm = docMapper.uidMapper().term(request.type(), request.id());
boolBuilder.mustNot(termQuery(uidTerm.field(), uidTerm.text()));
} catch (Exception e) {
listener.onFailure(e);
}
SearchRequest searchRequest = searchRequest(request.index()).types(request.type())
.listenerThreaded(request.listenerThreaded())
.source(searchSource()
.query(boolBuilder)
);
searchAction.execute(searchRequest, new ActionListener<SearchResponse>() {
@Override public void onResponse(SearchResponse response) {
listener.onResponse(response);
}
@Override public void onFailure(Throwable e) {
listener.onFailure(e);
}
});
}
@Override public void onFailure(Throwable e) {
listener.onFailure(e);
}
});
}
private void addMoreLikeThis(MoreLikeThisRequest request, BoolJsonQueryBuilder boolBuilder, FieldMapper fieldMapper, Fieldable field) {
MoreLikeThisFieldJsonQueryBuilder mlt = moreLikeThisFieldQuery(field.name())
.likeText(fieldMapper.valueAsString(field))
.percentTermsToMatch(request.percentTermsToMatch())
.boostTerms(request.boostTerms())
.boostTermsFactor(request.boostTermsFactor())
.minDocFreq(request.minDocFreq())
.maxDocFreq(request.maxDocFreq())
.minWordLen(request.minWordLen())
.maxWordLen(request.maxWordLen())
.minTermFrequency(request.minTermFrequency())
.maxQueryTerms(request.maxQueryTerms())
.stopWords(request.stopWords());
boolBuilder.should(mlt);
}
private class TransportHandler extends BaseTransportRequestHandler<MoreLikeThisRequest> {
@Override public MoreLikeThisRequest newInstance() {
return new MoreLikeThisRequest();
}
@Override public void messageReceived(MoreLikeThisRequest request, final TransportChannel channel) throws Exception {
// no need to have a threaded listener since we just send back a response
request.listenerThreaded(false);
execute(request, new ActionListener<SearchResponse>() {
@Override public void onResponse(SearchResponse result) {
try {
channel.sendResponse(result);
} catch (Exception e) {
onFailure(e);
}
}
@Override public void onFailure(Throwable e) {
try {
channel.sendResponse(e);
} catch (Exception e1) {
logger.warn("Failed to send response for get", e1);
}
}
});
}
@Override public boolean spawn() {
return false;
}
}
}

View File

@ -37,7 +37,7 @@ import static org.elasticsearch.action.Actions.*;
* <p>This is very handy to implement things like tag clouds and auto complete (using {@link #prefix(String)} or * <p>This is very handy to implement things like tag clouds and auto complete (using {@link #prefix(String)} or
* {@link #regexp(String)}). * {@link #regexp(String)}).
* *
* @author kimchy (Shay Banon) * @author kimchy (shay.banon)
*/ */
public class TermsRequest extends BroadcastOperationRequest { public class TermsRequest extends BroadcastOperationRequest {

View File

@ -31,6 +31,7 @@ import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.search.SearchScrollRequest;
@ -266,9 +267,40 @@ public interface Client {
*/ */
void execSearchScroll(SearchScrollRequest request, ActionListener<SearchResponse> listener); void execSearchScroll(SearchScrollRequest request, ActionListener<SearchResponse> listener);
/**
* A terms request to get terms in one or more indices of specific fields and their
* document frequencies (in how many document each term exists).
*
* @param request The term request
* @return The result future
* @see Requests#termsRequest(String...)
*/
ActionFuture<TermsResponse> terms(TermsRequest request); ActionFuture<TermsResponse> terms(TermsRequest request);
/**
* A terms request to get terms in one or more indices of specific fields and their
* document frequencies (in how many document each term exists).
*
* @param request The term request
* @param listener A listener to be notified of the result
* @return The result future
* @see Requests#termsRequest(String...)
*/
ActionFuture<TermsResponse> terms(TermsRequest request, ActionListener<TermsResponse> listener); ActionFuture<TermsResponse> terms(TermsRequest request, ActionListener<TermsResponse> listener);
/**
* A terms request to get terms in one or more indices of specific fields and their
* document frequencies (in how many document each term exists).
*
* @param request The term request
* @param listener A listener to be notified of the result
* @see Requests#termsRequest(String...)
*/
void execTerms(TermsRequest request, ActionListener<TermsResponse> listener); void execTerms(TermsRequest request, ActionListener<TermsResponse> listener);
ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request);
ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener);
void execMoreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener);
} }

View File

@ -38,6 +38,7 @@ import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.deletebyquery.DeleteByQueryRequest; import org.elasticsearch.action.deletebyquery.DeleteByQueryRequest;
import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.terms.TermsRequest; import org.elasticsearch.action.terms.TermsRequest;
@ -109,10 +110,26 @@ public class Requests {
return new CountRequest(indices); return new CountRequest(indices);
} }
/**
* Terms request represent a request to get terms in one or more indices of specific fields and their
* document frequencies (in how many document each term exists).
*
* @param indices The indices the delete by query against. Use <tt>null</tt> or <tt>_all</tt> to execute against all indices
* @return The terms request
* @see org.elasticsearch.client.Client#terms(org.elasticsearch.action.terms.TermsRequest)
*/
public static TermsRequest termsRequest(String... indices) { public static TermsRequest termsRequest(String... indices) {
return new TermsRequest(indices); return new TermsRequest(indices);
} }
/**
* @param index
* @return
*/
public static MoreLikeThisRequest moreLikeThisRequest(String index) {
return new MoreLikeThisRequest(index);
}
/** /**
* Creates a search request against one or more indices. Note, the search source must be set either using the * Creates a search request against one or more indices. Note, the search source must be set either using the
* actual JSON search source, or the {@link org.elasticsearch.search.builder.SearchSourceBuilder}. * actual JSON search source, or the {@link org.elasticsearch.search.builder.SearchSourceBuilder}.

View File

@ -37,6 +37,8 @@ import org.elasticsearch.action.get.TransportGetAction;
import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.index.TransportIndexAction; import org.elasticsearch.action.index.TransportIndexAction;
import org.elasticsearch.action.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.mlt.TransportMoreLikeThisAction;
import org.elasticsearch.action.search.*; import org.elasticsearch.action.search.*;
import org.elasticsearch.action.terms.TermsRequest; import org.elasticsearch.action.terms.TermsRequest;
import org.elasticsearch.action.terms.TermsResponse; import org.elasticsearch.action.terms.TermsResponse;
@ -69,11 +71,13 @@ public class ServerClient extends AbstractComponent implements Client {
private final TransportTermsAction termsAction; private final TransportTermsAction termsAction;
private final TransportMoreLikeThisAction moreLikeThisAction;
@Inject public ServerClient(Settings settings, ServerAdminClient admin, @Inject public ServerClient(Settings settings, ServerAdminClient admin,
TransportIndexAction indexAction, TransportDeleteAction deleteAction, TransportIndexAction indexAction, TransportDeleteAction deleteAction,
TransportDeleteByQueryAction deleteByQueryAction, TransportGetAction getAction, TransportCountAction countAction, TransportDeleteByQueryAction deleteByQueryAction, TransportGetAction getAction, TransportCountAction countAction,
TransportSearchAction searchAction, TransportSearchScrollAction searchScrollAction, TransportSearchAction searchAction, TransportSearchScrollAction searchScrollAction,
TransportTermsAction termsAction) { TransportTermsAction termsAction, TransportMoreLikeThisAction moreLikeThisAction) {
super(settings); super(settings);
this.admin = admin; this.admin = admin;
this.indexAction = indexAction; this.indexAction = indexAction;
@ -84,6 +88,7 @@ public class ServerClient extends AbstractComponent implements Client {
this.searchAction = searchAction; this.searchAction = searchAction;
this.searchScrollAction = searchScrollAction; this.searchScrollAction = searchScrollAction;
this.termsAction = termsAction; this.termsAction = termsAction;
this.moreLikeThisAction = moreLikeThisAction;
} }
@Override public void close() { @Override public void close() {
@ -189,4 +194,16 @@ public class ServerClient extends AbstractComponent implements Client {
@Override public void execTerms(TermsRequest request, ActionListener<TermsResponse> listener) { @Override public void execTerms(TermsRequest request, ActionListener<TermsResponse> listener) {
termsAction.execute(request, listener); termsAction.execute(request, listener);
} }
@Override public ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request) {
return moreLikeThisAction.submit(request);
}
@Override public ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener) {
return moreLikeThisAction.submit(request, listener);
}
@Override public void execMoreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener) {
moreLikeThisAction.execute(request, listener);
}
} }

View File

@ -36,6 +36,7 @@ import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.search.SearchScrollRequest;
@ -304,4 +305,16 @@ public class TransportClient implements Client {
@Override public void execTerms(TermsRequest request, ActionListener<TermsResponse> listener) { @Override public void execTerms(TermsRequest request, ActionListener<TermsResponse> listener) {
internalClient.terms(request, listener); internalClient.terms(request, listener);
} }
@Override public ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request) {
return internalClient.moreLikeThis(request);
}
@Override public ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener) {
return internalClient.moreLikeThis(request, listener);
}
@Override public void execMoreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener) {
internalClient.execMoreLikeThis(request, listener);
}
} }

View File

@ -0,0 +1,42 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.elasticsearch.client.transport.action.mlt;
import com.google.inject.Inject;
import org.elasticsearch.action.TransportActions;
import org.elasticsearch.action.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.action.support.BaseClientTransportAction;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.util.settings.Settings;
/**
* @author kimchy (shay.banon)
*/
public class ClientTransportMoreLikeThisAction extends BaseClientTransportAction<MoreLikeThisRequest, SearchResponse> {
@Inject public ClientTransportMoreLikeThisAction(Settings settings, TransportService transportService) {
super(settings, transportService, SearchResponse.class);
}
@Override protected String action() {
return TransportActions.MORE_LIKE_THIS;
}
}

View File

@ -33,6 +33,7 @@ import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.search.SearchScrollRequest;
@ -46,6 +47,7 @@ import org.elasticsearch.client.transport.action.delete.ClientTransportDeleteAct
import org.elasticsearch.client.transport.action.deletebyquery.ClientTransportDeleteByQueryAction; import org.elasticsearch.client.transport.action.deletebyquery.ClientTransportDeleteByQueryAction;
import org.elasticsearch.client.transport.action.get.ClientTransportGetAction; import org.elasticsearch.client.transport.action.get.ClientTransportGetAction;
import org.elasticsearch.client.transport.action.index.ClientTransportIndexAction; import org.elasticsearch.client.transport.action.index.ClientTransportIndexAction;
import org.elasticsearch.client.transport.action.mlt.ClientTransportMoreLikeThisAction;
import org.elasticsearch.client.transport.action.search.ClientTransportSearchAction; import org.elasticsearch.client.transport.action.search.ClientTransportSearchAction;
import org.elasticsearch.client.transport.action.search.ClientTransportSearchScrollAction; import org.elasticsearch.client.transport.action.search.ClientTransportSearchScrollAction;
import org.elasticsearch.client.transport.action.terms.ClientTransportTermsAction; import org.elasticsearch.client.transport.action.terms.ClientTransportTermsAction;
@ -78,11 +80,13 @@ public class InternalTransportClient extends AbstractComponent implements Client
private final ClientTransportTermsAction termsAction; private final ClientTransportTermsAction termsAction;
private final ClientTransportMoreLikeThisAction moreLikeThisAction;
@Inject public InternalTransportClient(Settings settings, TransportClientNodesService nodesService, InternalTransportAdminClient adminClient, @Inject public InternalTransportClient(Settings settings, TransportClientNodesService nodesService, InternalTransportAdminClient adminClient,
ClientTransportIndexAction indexAction, ClientTransportDeleteAction deleteAction, ClientTransportGetAction getAction, ClientTransportIndexAction indexAction, ClientTransportDeleteAction deleteAction, ClientTransportGetAction getAction,
ClientTransportDeleteByQueryAction deleteByQueryAction, ClientTransportCountAction countAction, ClientTransportDeleteByQueryAction deleteByQueryAction, ClientTransportCountAction countAction,
ClientTransportSearchAction searchAction, ClientTransportSearchScrollAction searchScrollAction, ClientTransportSearchAction searchAction, ClientTransportSearchScrollAction searchScrollAction,
ClientTransportTermsAction termsAction) { ClientTransportTermsAction termsAction, ClientTransportMoreLikeThisAction moreLikeThisAction) {
super(settings); super(settings);
this.nodesService = nodesService; this.nodesService = nodesService;
this.adminClient = adminClient; this.adminClient = adminClient;
@ -95,6 +99,7 @@ public class InternalTransportClient extends AbstractComponent implements Client
this.searchAction = searchAction; this.searchAction = searchAction;
this.searchScrollAction = searchScrollAction; this.searchScrollAction = searchScrollAction;
this.termsAction = termsAction; this.termsAction = termsAction;
this.moreLikeThisAction = moreLikeThisAction;
} }
@Override public void close() { @Override public void close() {
@ -304,4 +309,29 @@ public class InternalTransportClient extends AbstractComponent implements Client
} }
}); });
} }
@Override public ActionFuture<SearchResponse> moreLikeThis(final MoreLikeThisRequest request) {
return nodesService.execute(new TransportClientNodesService.NodeCallback<ActionFuture<SearchResponse>>() {
@Override public ActionFuture<SearchResponse> doWithNode(Node node) throws ElasticSearchException {
return moreLikeThisAction.submit(node, request);
}
});
}
@Override public ActionFuture<SearchResponse> moreLikeThis(final MoreLikeThisRequest request, final ActionListener<SearchResponse> listener) {
return nodesService.execute(new TransportClientNodesService.NodeCallback<ActionFuture<SearchResponse>>() {
@Override public ActionFuture<SearchResponse> doWithNode(Node node) throws ElasticSearchException {
return moreLikeThisAction.submit(node, request, listener);
}
});
}
@Override public void execMoreLikeThis(final MoreLikeThisRequest request, final ActionListener<SearchResponse> listener) {
nodesService.execute(new TransportClientNodesService.NodeCallback<Void>() {
@Override public Void doWithNode(Node node) throws ElasticSearchException {
moreLikeThisAction.submit(node, request);
return null;
}
});
}
} }

View File

@ -0,0 +1,76 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.elasticsearch.index.query.json;
import org.apache.lucene.search.BooleanClause;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.ArrayList;
/**
* @author kimchy (Shay Banon)
*/
public class BoolJsonFilterBuilder extends BaseJsonQueryBuilder {
private ArrayList<Clause> clauses = new ArrayList<Clause>();
public BoolJsonFilterBuilder must(JsonFilterBuilder filterBuilder) {
clauses.add(new Clause(filterBuilder, BooleanClause.Occur.MUST));
return this;
}
public BoolJsonFilterBuilder mustNot(JsonFilterBuilder filterBuilder) {
clauses.add(new Clause(filterBuilder, BooleanClause.Occur.MUST_NOT));
return this;
}
public BoolJsonFilterBuilder should(JsonFilterBuilder filterBuilder) {
clauses.add(new Clause(filterBuilder, BooleanClause.Occur.SHOULD));
return this;
}
@Override protected void doJson(JsonBuilder builder, Params params) throws IOException {
builder.startObject("bool");
for (Clause clause : clauses) {
if (clause.occur == BooleanClause.Occur.MUST) {
builder.field("must");
clause.filterBuilder.toJson(builder, params);
} else if (clause.occur == BooleanClause.Occur.MUST_NOT) {
builder.field("mustNot");
clause.filterBuilder.toJson(builder, params);
} else if (clause.occur == BooleanClause.Occur.SHOULD) {
builder.field("should");
clause.filterBuilder.toJson(builder, params);
}
}
builder.endObject();
}
private static class Clause {
final JsonFilterBuilder filterBuilder;
final BooleanClause.Occur occur;
private Clause(JsonFilterBuilder filterBuilder, BooleanClause.Occur occur) {
this.filterBuilder = filterBuilder;
this.occur = occur;
}
}
}

View File

@ -88,7 +88,7 @@ public class BoolJsonQueryBuilder extends BaseJsonQueryBuilder {
if (disableCoord != null) { if (disableCoord != null) {
builder.field("disableCoord", disableCoord); builder.field("disableCoord", disableCoord);
} }
if (minimumNumberShouldMatch == -1) { if (minimumNumberShouldMatch != -1) {
builder.field("minimumNumberShouldMatch", minimumNumberShouldMatch); builder.field("minimumNumberShouldMatch", minimumNumberShouldMatch);
} }
builder.endObject(); builder.endObject();

View File

@ -76,6 +76,10 @@ public abstract class JsonFilterBuilders {
return new QueryJsonFilterBuilder(queryBuilder); return new QueryJsonFilterBuilder(queryBuilder);
} }
public static BoolJsonFilterBuilder boolFilter() {
return new BoolJsonFilterBuilder();
}
private JsonFilterBuilders() { private JsonFilterBuilders() {
} }

View File

@ -92,7 +92,7 @@ public class MoreLikeThisFieldJsonQueryBuilder extends BaseJsonQueryBuilder {
return this; return this;
} }
public MoreLikeThisFieldJsonQueryBuilder boostTerms(boolean boostTerms) { public MoreLikeThisFieldJsonQueryBuilder boostTerms(Boolean boostTerms) {
this.boostTerms = boostTerms; this.boostTerms = boostTerms;
return this; return this;
} }

View File

@ -0,0 +1,64 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.elasticsearch.util.lucene.search;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.elasticsearch.util.lucene.Lucene;
import org.testng.annotations.Test;
import static org.elasticsearch.util.lucene.DocumentBuilder.*;
import static org.elasticsearch.util.lucene.IndexWriters.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
/**
* @author kimchy (shay.banon)
*/
@Test
public class MoreLikeThisQueryTests {
@Test public void testSimple() throws Exception {
Directory dir = new RAMDirectory();
IndexWriter indexWriter = new IndexWriter(dir, Lucene.STANDARD_ANALYZER, true, IndexWriter.MaxFieldLength.UNLIMITED);
indexWriter.commit();
assertThat("Index is empty after creation and commit", estimateRamSize(indexWriter), equalTo(0l));
indexWriter.addDocument(doc().add(field("_id", "1")).add(field("text", "lucene")).build());
indexWriter.addDocument(doc().add(field("_id", "2")).add(field("text", "lucene release")).build());
IndexReader reader = indexWriter.getReader();
IndexSearcher searcher = new IndexSearcher(reader);
MoreLikeThisQuery mltQuery = new MoreLikeThisQuery("lucene", new String[]{"text"}, Lucene.STANDARD_ANALYZER);
mltQuery.setLikeText("lucene");
mltQuery.setMinTermFrequency(1);
mltQuery.setMinDocFreq(1);
long count = Lucene.count(searcher, mltQuery, -1);
assertThat(count, equalTo(2l));
reader.close();
indexWriter.close();
}
}

View File

@ -1,189 +0,0 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.elasticsearch.test.integration.client.transport;
import org.elasticsearch.action.admin.indices.flush.FlushResponse;
import org.elasticsearch.action.admin.indices.optimize.OptimizeResponse;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.action.admin.indices.status.IndicesStatusResponse;
import org.elasticsearch.action.count.CountResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.NoNodeAvailableException;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.server.internal.InternalServer;
import org.elasticsearch.test.integration.AbstractServersTests;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.util.Unicode;
import org.elasticsearch.util.transport.TransportAddress;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.index.query.json.JsonQueryBuilders.*;
import static org.elasticsearch.util.settings.ImmutableSettings.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
/**
* @author kimchy (Shay Banon)
*/
public class SimpleSingleTransportClientTests extends AbstractServersTests {
private TransportClient client;
@AfterMethod public void closeServers() {
closeAllServers();
if (client != null) {
client.close();
}
}
@Test public void testOnlyWithTransportAddress() throws Exception {
startServer("server1");
TransportAddress server1Address = ((InternalServer) server("server1")).injector().getInstance(TransportService.class).boundAddress().publishAddress();
client = new TransportClient(settingsBuilder().putBoolean("discovery.enabled", false).build());
client.addTransportAddress(server1Address);
testSimpleActions(client);
}
/*@Test*/
public void testWithDiscovery() throws Exception {
startServer("server1");
client = new TransportClient(settingsBuilder().putBoolean("discovery.enabled", true).build());
// wait a bit so nodes will be discovered
Thread.sleep(1000);
testSimpleActions(client);
}
private void testSimpleActions(Client client) throws Exception {
logger.info("Creating index test");
client.admin().indices().create(createIndexRequest("test")).actionGet();
Thread.sleep(500);
IndexResponse indexResponse = client.index(Requests.indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
assertThat(indexResponse.id(), equalTo("1"));
assertThat(indexResponse.type(), equalTo("type1"));
logger.info("Refreshing");
RefreshResponse refreshResponse = client.admin().indices().refresh(refreshRequest("test")).actionGet();
assertThat(refreshResponse.successfulShards(), equalTo(5));
assertThat(refreshResponse.failedShards(), equalTo(5)); // 5 are not active, since we started just one server
logger.info("Optimizing");
OptimizeResponse optimizeResponse = client.admin().indices().optimize(optimizeRequest("test")).actionGet();
assertThat(optimizeResponse.successfulShards(), equalTo(5));
assertThat(optimizeResponse.failedShards(), equalTo(5)); // 5 are not active, since we started just one server
IndicesStatusResponse indicesStatusResponse = client.admin().indices().status(indicesStatus()).actionGet();
assertThat(indicesStatusResponse.successfulShards(), equalTo(5));
assertThat(indicesStatusResponse.failedShards(), equalTo(5)); // 5 are not active, since we started just one server
assertThat(indicesStatusResponse.indices().size(), equalTo(1));
assertThat(indicesStatusResponse.index("test").shards().size(), equalTo(5)); // 5 index shards (1 with 1 backup)
assertThat(indicesStatusResponse.index("test").docs().numDocs(), equalTo(1l));
GetResponse getResult;
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("1").threadedOperation(false)).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client.get(getRequest("test").type("type1").id("1").threadedOperation(true)).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
}
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat(getResult.empty(), equalTo(true));
}
DeleteResponse deleteResponse = client.delete(deleteRequest("test").type("type1").id("1")).actionGet();
assertThat(deleteResponse.id(), equalTo("1"));
assertThat(deleteResponse.type(), equalTo("type1"));
client.admin().indices().refresh(refreshRequest("test")).actionGet();
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat(getResult.empty(), equalTo(true));
}
client.index(Requests.indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
client.index(Requests.indexRequest("test").type("type1").id("2").source(source("2", "test"))).actionGet();
FlushResponse flushResult = client.admin().indices().flush(flushRequest("test")).actionGet();
assertThat(flushResult.successfulShards(), equalTo(5));
assertThat(flushResult.failedShards(), equalTo(5)); // we only start one server
client.admin().indices().refresh(refreshRequest("test")).actionGet();
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("2", "test")));
}
// check count
for (int i = 0; i < 5; i++) {
// test successful
CountResponse countResponse = client.count(countRequest("test").querySource(termQuery("_type", "type1"))).actionGet();
assertThat(countResponse.count(), equalTo(2l));
assertThat(countResponse.successfulShards(), equalTo(5));
assertThat(countResponse.failedShards(), equalTo(0));
// test failed (simply query that can't be parsed)
countResponse = client.count(countRequest("test").querySource(Unicode.fromStringAsBytes("{ term : { _type : \"type1 } }"))).actionGet();
assertThat(countResponse.count(), equalTo(0l));
assertThat(countResponse.successfulShards(), equalTo(0));
assertThat(countResponse.failedShards(), equalTo(5));
}
DeleteByQueryResponse queryResponse = client.deleteByQuery(deleteByQueryRequest("test").querySource(termQuery("name", "test2"))).actionGet();
assertThat(queryResponse.index("test").successfulShards(), equalTo(5));
assertThat(queryResponse.index("test").failedShards(), equalTo(0));
client.admin().indices().refresh(refreshRequest("test")).actionGet();
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat("cycle #" + i, getResult.empty(), equalTo(false));
}
// stop the server
closeServer("server1");
// it should try and reconnect
try {
client.index(Requests.indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
assert false : "should fail...";
} catch (NoNodeAvailableException e) {
// all is well
}
}
private String source(String id, String nameValue) {
return "{ type1 : { \"id\" : \"" + id + "\", \"name\" : \"" + nameValue + "\" } }";
}
}

View File

@ -0,0 +1,49 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.elasticsearch.test.integration.client.transport;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.server.internal.InternalServer;
import org.elasticsearch.test.integration.document.DocumentActionsTests;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.util.transport.TransportAddress;
import static org.elasticsearch.util.settings.ImmutableSettings.*;
/**
* @author kimchy (shay.banon)
*/
public class TransportClientDocumentActionsTests extends DocumentActionsTests {
@Override protected Client getClient1() {
TransportAddress server1Address = ((InternalServer) server("server1")).injector().getInstance(TransportService.class).boundAddress().publishAddress();
TransportClient client = new TransportClient(settingsBuilder().putBoolean("discovery.enabled", false).build());
client.addTransportAddress(server1Address);
return client;
}
@Override protected Client getClient2() {
TransportAddress server1Address = ((InternalServer) server("server2")).injector().getInstance(TransportService.class).boundAddress().publishAddress();
TransportClient client = new TransportClient(settingsBuilder().putBoolean("discovery.enabled", false).build());
client.addTransportAddress(server1Address);
return client;
}
}

View File

@ -30,9 +30,11 @@ import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.broadcast.BroadcastOperationThreading; import org.elasticsearch.action.support.broadcast.BroadcastOperationThreading;
import org.elasticsearch.client.Client;
import org.elasticsearch.test.integration.AbstractServersTests; import org.elasticsearch.test.integration.AbstractServersTests;
import org.elasticsearch.util.Unicode; import org.elasticsearch.util.Unicode;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.elasticsearch.client.Requests.*; import static org.elasticsearch.client.Requests.*;
@ -45,34 +47,51 @@ import static org.hamcrest.Matchers.*;
*/ */
public class DocumentActionsTests extends AbstractServersTests { public class DocumentActionsTests extends AbstractServersTests {
private Client client1;
private Client client2;
@BeforeMethod public void startServers() {
startServer("server1");
startServer("server2");
client1 = getClient1();
client2 = getClient2();
}
@AfterMethod public void closeServers() { @AfterMethod public void closeServers() {
client1.close();
client2.close();
closeAllServers(); closeAllServers();
} }
@Test public void testIndexActions() throws Exception { protected Client getClient1() {
startServer("server1"); return client("server1");
startServer("server2"); }
protected Client getClient2() {
return client("server2");
}
@Test public void testIndexActions() throws Exception {
logger.info("Creating index test"); logger.info("Creating index test");
client("server1").admin().indices().create(createIndexRequest("test")).actionGet(); client1.admin().indices().create(createIndexRequest("test")).actionGet();
logger.info("Running Cluster Health"); logger.info("Running Cluster Health");
ClusterHealthResponse clusterHealth = client("server1").admin().cluster().health(clusterHealth().waitForGreenStatus()).actionGet(); ClusterHealthResponse clusterHealth = client1.admin().cluster().health(clusterHealth().waitForGreenStatus()).actionGet();
logger.info("Done Cluster Health, status " + clusterHealth.status()); logger.info("Done Cluster Health, status " + clusterHealth.status());
assertThat(clusterHealth.timedOut(), equalTo(false)); assertThat(clusterHealth.timedOut(), equalTo(false));
assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN)); assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN));
logger.info("Indexing [type1/1]"); logger.info("Indexing [type1/1]");
IndexResponse indexResponse = client("server1").index(indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet(); IndexResponse indexResponse = client1.index(indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
assertThat(indexResponse.id(), equalTo("1")); assertThat(indexResponse.id(), equalTo("1"));
assertThat(indexResponse.type(), equalTo("type1")); assertThat(indexResponse.type(), equalTo("type1"));
logger.info("Refreshing"); logger.info("Refreshing");
RefreshResponse refreshResponse = client("server1").admin().indices().refresh(refreshRequest("test")).actionGet(); RefreshResponse refreshResponse = client1.admin().indices().refresh(refreshRequest("test")).actionGet();
assertThat(refreshResponse.successfulShards(), equalTo(10)); assertThat(refreshResponse.successfulShards(), equalTo(10));
assertThat(refreshResponse.failedShards(), equalTo(0)); assertThat(refreshResponse.failedShards(), equalTo(0));
logger.info("Optimizing"); logger.info("Optimizing");
OptimizeResponse optimizeResponse = client("server1").admin().indices().optimize(optimizeRequest("test")).actionGet(); OptimizeResponse optimizeResponse = client1.admin().indices().optimize(optimizeRequest("test")).actionGet();
assertThat(optimizeResponse.successfulShards(), equalTo(10)); assertThat(optimizeResponse.successfulShards(), equalTo(10));
assertThat(optimizeResponse.failedShards(), equalTo(0)); assertThat(optimizeResponse.failedShards(), equalTo(0));
@ -80,48 +99,48 @@ public class DocumentActionsTests extends AbstractServersTests {
logger.info("Get [type1/1]"); logger.info("Get [type1/1]");
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("1").threadedOperation(false)).actionGet(); getResult = client1.get(getRequest("test").type("type1").id("1").threadedOperation(false)).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test"))); assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client("server1").get(getRequest("test").type("type1").id("1").threadedOperation(true)).actionGet(); getResult = client1.get(getRequest("test").type("type1").id("1").threadedOperation(true)).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test"))); assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
} }
logger.info("Get [type1/2] (should be empty)"); logger.info("Get [type1/2] (should be empty)");
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("2")).actionGet(); getResult = client1.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat(getResult.empty(), equalTo(true)); assertThat(getResult.empty(), equalTo(true));
} }
logger.info("Delete [type1/1]"); logger.info("Delete [type1/1]");
DeleteResponse deleteResponse = client("server1").delete(deleteRequest("test").type("type1").id("1")).actionGet(); DeleteResponse deleteResponse = client1.delete(deleteRequest("test").type("type1").id("1")).actionGet();
assertThat(deleteResponse.id(), equalTo("1")); assertThat(deleteResponse.id(), equalTo("1"));
assertThat(deleteResponse.type(), equalTo("type1")); assertThat(deleteResponse.type(), equalTo("type1"));
logger.info("Refreshing"); logger.info("Refreshing");
client("server1").admin().indices().refresh(refreshRequest("test")).actionGet(); client1.admin().indices().refresh(refreshRequest("test")).actionGet();
logger.info("Get [type1/1] (should be empty)"); logger.info("Get [type1/1] (should be empty)");
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("1")).actionGet(); getResult = client1.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat(getResult.empty(), equalTo(true)); assertThat(getResult.empty(), equalTo(true));
} }
logger.info("Index [type1/1]"); logger.info("Index [type1/1]");
client("server1").index(indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet(); client1.index(indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
logger.info("Index [type1/2]"); logger.info("Index [type1/2]");
client("server1").index(indexRequest("test").type("type1").id("2").source(source("2", "test"))).actionGet(); client1.index(indexRequest("test").type("type1").id("2").source(source("2", "test"))).actionGet();
logger.info("Flushing"); logger.info("Flushing");
FlushResponse flushResult = client("server1").admin().indices().flush(flushRequest("test")).actionGet(); FlushResponse flushResult = client1.admin().indices().flush(flushRequest("test")).actionGet();
assertThat(flushResult.successfulShards(), equalTo(10)); assertThat(flushResult.successfulShards(), equalTo(10));
assertThat(flushResult.failedShards(), equalTo(0)); assertThat(flushResult.failedShards(), equalTo(0));
logger.info("Refreshing"); logger.info("Refreshing");
client("server1").admin().indices().refresh(refreshRequest("test")).actionGet(); client1.admin().indices().refresh(refreshRequest("test")).actionGet();
logger.info("Get [type1/1] and [type1/2]"); logger.info("Get [type1/1] and [type1/2]");
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("1")).actionGet(); getResult = client1.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test"))); assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client("server1").get(getRequest("test").type("type1").id("2")).actionGet(); getResult = client1.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("2", "test"))); assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("2", "test")));
} }
@ -129,23 +148,23 @@ public class DocumentActionsTests extends AbstractServersTests {
// check count // check count
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
// test successful // test successful
CountResponse countResponse = client("server1").count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.NO_THREADS)).actionGet(); CountResponse countResponse = client1.count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.NO_THREADS)).actionGet();
assertThat(countResponse.count(), equalTo(2l)); assertThat(countResponse.count(), equalTo(2l));
assertThat(countResponse.successfulShards(), equalTo(5)); assertThat(countResponse.successfulShards(), equalTo(5));
assertThat(countResponse.failedShards(), equalTo(0)); assertThat(countResponse.failedShards(), equalTo(0));
countResponse = client("server1").count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.SINGLE_THREAD)).actionGet(); countResponse = client1.count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.SINGLE_THREAD)).actionGet();
assertThat(countResponse.count(), equalTo(2l)); assertThat(countResponse.count(), equalTo(2l));
assertThat(countResponse.successfulShards(), equalTo(5)); assertThat(countResponse.successfulShards(), equalTo(5));
assertThat(countResponse.failedShards(), equalTo(0)); assertThat(countResponse.failedShards(), equalTo(0));
countResponse = client("server1").count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.THREAD_PER_SHARD)).actionGet(); countResponse = client1.count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.THREAD_PER_SHARD)).actionGet();
assertThat(countResponse.count(), equalTo(2l)); assertThat(countResponse.count(), equalTo(2l));
assertThat(countResponse.successfulShards(), equalTo(5)); assertThat(countResponse.successfulShards(), equalTo(5));
assertThat(countResponse.failedShards(), equalTo(0)); assertThat(countResponse.failedShards(), equalTo(0));
// test failed (simply query that can't be parsed) // test failed (simply query that can't be parsed)
countResponse = client("server1").count(countRequest("test").querySource(Unicode.fromStringAsBytes("{ term : { _type : \"type1 } }"))).actionGet(); countResponse = client1.count(countRequest("test").querySource(Unicode.fromStringAsBytes("{ term : { _type : \"type1 } }"))).actionGet();
assertThat(countResponse.count(), equalTo(0l)); assertThat(countResponse.count(), equalTo(0l));
assertThat(countResponse.successfulShards(), equalTo(0)); assertThat(countResponse.successfulShards(), equalTo(0));
@ -153,16 +172,16 @@ public class DocumentActionsTests extends AbstractServersTests {
} }
logger.info("Delete by query"); logger.info("Delete by query");
DeleteByQueryResponse queryResponse = client("server2").deleteByQuery(deleteByQueryRequest("test").querySource(termQuery("name", "test2"))).actionGet(); DeleteByQueryResponse queryResponse = client2.deleteByQuery(deleteByQueryRequest("test").querySource(termQuery("name", "test2"))).actionGet();
assertThat(queryResponse.index("test").successfulShards(), equalTo(5)); assertThat(queryResponse.index("test").successfulShards(), equalTo(5));
assertThat(queryResponse.index("test").failedShards(), equalTo(0)); assertThat(queryResponse.index("test").failedShards(), equalTo(0));
client("server1").admin().indices().refresh(refreshRequest("test")).actionGet(); client1.admin().indices().refresh(refreshRequest("test")).actionGet();
logger.info("Get [type1/1] and [type1/2], should be empty"); logger.info("Get [type1/1] and [type1/2], should be empty");
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("1")).actionGet(); getResult = client1.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test"))); assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client("server1").get(getRequest("test").type("type1").id("2")).actionGet(); getResult = client1.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat("cycle #" + i, getResult.empty(), equalTo(false)); assertThat("cycle #" + i, getResult.empty(), equalTo(false));
} }
} }

View File

@ -0,0 +1,86 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.elasticsearch.test.integration.document;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.test.integration.AbstractServersTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.util.json.JsonBuilder.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
/**
* @author kimchy (shay.banon)
*/
public class MoreLikeThisActionTests extends AbstractServersTests {
private Client client1;
private Client client2;
@BeforeMethod public void startServers() {
startServer("server1");
startServer("server2");
client1 = getClient1();
client2 = getClient2();
}
@AfterMethod public void closeServers() {
client1.close();
client2.close();
closeAllServers();
}
protected Client getClient1() {
return client("server1");
}
protected Client getClient2() {
return client("server2");
}
@Test public void testSimpleMoreLikeThis() throws Exception {
logger.info("Creating index test");
client1.admin().indices().create(createIndexRequest("test")).actionGet();
logger.info("Running Cluster Health");
ClusterHealthResponse clusterHealth = client1.admin().cluster().health(clusterHealth().waitForGreenStatus()).actionGet();
logger.info("Done Cluster Health, status " + clusterHealth.status());
assertThat(clusterHealth.timedOut(), equalTo(false));
assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN));
logger.info("Indexing...");
client1.index(indexRequest("test").type("type1").id("1").source(binaryJsonBuilder().startObject().field("text", "lucene").endObject())).actionGet();
client1.index(indexRequest("test").type("type1").id("2").source(binaryJsonBuilder().startObject().field("text", "lucene release").endObject())).actionGet();
client1.admin().indices().refresh(refreshRequest()).actionGet();
logger.info("Running moreLikeThis");
SearchResponse mltResponse = client1.moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFrequency(1).minDocFreq(1)).actionGet();
assertThat(mltResponse.successfulShards(), equalTo(5));
assertThat(mltResponse.failedShards(), equalTo(0));
assertThat(mltResponse.hits().totalHits(), equalTo(1l));
}
}

View File

@ -0,0 +1,6 @@
cluster:
routing:
schedule: 100ms
index:
numberOfShards: 5
numberOfReplicas: 1