diff --git a/src/main/java/org/elasticsearch/index/shard/IndexShard.java b/src/main/java/org/elasticsearch/index/shard/IndexShard.java index 2e155a7a92069..68845ec0306e8 100644 --- a/src/main/java/org/elasticsearch/index/shard/IndexShard.java +++ b/src/main/java/org/elasticsearch/index/shard/IndexShard.java @@ -31,6 +31,7 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchIllegalArgumentException; import org.elasticsearch.ElasticsearchIllegalStateException; +import org.elasticsearch.Version; import org.elasticsearch.action.WriteFailureException; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.optimize.OptimizeRequest; @@ -56,6 +57,8 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.util.concurrent.AbstractRefCounted; import org.elasticsearch.common.util.concurrent.FutureUtils; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.VersionType; import org.elasticsearch.index.aliases.IndexAliasesService; @@ -87,6 +90,8 @@ import org.elasticsearch.index.percolator.PercolatorQueriesRegistry; import org.elasticsearch.index.percolator.stats.ShardPercolateService; import org.elasticsearch.index.query.IndexQueryParserService; +import org.elasticsearch.index.query.ParsedQuery; +import org.elasticsearch.index.query.QueryParsingException; import org.elasticsearch.index.recovery.RecoveryStats; import org.elasticsearch.index.refresh.RefreshStats; import org.elasticsearch.index.search.nested.NonNestedDocsFilter; @@ -540,7 +545,24 @@ public Engine.DeleteByQuery prepareDeleteByQuery(BytesReference source, @Nullabl if (types == null) { types = Strings.EMPTY_ARRAY; } - Query query = queryParserService.parseQuery(source).query(); + Query query; + try { + query = queryParserService.parseQuery(source).query(); + } catch (QueryParsingException ex) { + // for BWC we try to parse directly the query since pre 1.0.0.Beta2 we didn't require a top level query field + if (Version.indexCreated(config.getIndexSettings()).onOrBefore(Version.V_1_0_0_Beta2)) { + try { + XContentParser parser = XContentHelper.createParser(source); + ParsedQuery parse = queryParserService.parse(parser); + query = parse.query(); + } catch (Throwable t) { + ex.addSuppressed(t); + throw ex; + } + } else { + throw ex; + } + } query = filterQueryIfNeeded(query, types); Filter aliasFilter = indexAliasesService.aliasFilter(filteringAliases); diff --git a/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java b/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java index bb6fdab587b3d..6eed282df1e11 100644 --- a/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java +++ b/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java @@ -19,10 +19,15 @@ package org.elasticsearch.index.shard; import org.elasticsearch.ElasticsearchIllegalArgumentException; +import org.elasticsearch.Version; import org.elasticsearch.action.admin.indices.stats.IndexStats; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.engine.Engine; +import org.elasticsearch.index.query.QueryParsingException; +import org.elasticsearch.index.translog.Translog; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.test.ElasticsearchSingleNodeTest; import org.junit.Test; @@ -116,4 +121,32 @@ public void run() { assertNotNull(indexStats.getShards()[0].getCommitStats().getUserData().get(Engine.SYNC_COMMIT_ID)); } + public void testDeleteByQueryBWC() { + Version version = randomVersion(); + assertAcked(client().admin().indices().prepareCreate("test") + .setSettings(SETTING_NUMBER_OF_SHARDS, 1, SETTING_NUMBER_OF_REPLICAS, 0, IndexMetaData.SETTING_VERSION_CREATED, version.id)); + ensureGreen("test"); + client().prepareIndex("test", "person").setSource("{ \"user\" : \"kimchy\" }").get(); + + IndicesService indicesService = getInstanceFromNode(IndicesService.class); + IndexService test = indicesService.indexService("test"); + IndexShard shard = test.shard(0); + int numDocs = 1; + shard.state = IndexShardState.RECOVERING; + try { + shard.performRecoveryOperation(new Translog.DeleteByQuery(new Engine.DeleteByQuery(null, new BytesArray("{\"term\" : { \"user\" : \"kimchy\" }}"), null, null, null, Engine.Operation.Origin.RECOVERY, 0, "person"))); + assertTrue(version.onOrBefore(Version.V_1_0_0_Beta2)); + numDocs = 0; + } catch (QueryParsingException ex) { + assertTrue(version.after(Version.V_1_0_0_Beta2)); + } finally { + shard.state = IndexShardState.STARTED; + } + shard.engine().refresh("foo"); + + try (Engine.Searcher searcher = shard.engine().acquireSearcher("foo")) { + assertEquals(numDocs, searcher.reader().numDocs()); + } + } + }