mirror of https://github.com/apache/lucene.git
SOLR-11617: rename alias metadata to properties
This commit is contained in:
parent
55ba89ef42
commit
bf6503ba58
|
@ -148,8 +148,8 @@ New Features
|
|||
|
||||
* SOLR-11782: Refactor LatchWatcher.await to protect against spurious wakeup (Tomás Fernández Löbbe, David Smiley, Dawid Weiss)
|
||||
|
||||
* SOLR-11617: Alias metadata is now mutable via a new MODIFYALIAS command. Metadata is returned from LISTALIASES.
|
||||
(Gus Heck via David Smiley)
|
||||
* SOLR-11617: Alias properties (formerly "metadata") are now mutable via a new ALIASPROP command.
|
||||
These properties are returned from LISTALIASES. (Gus Heck via David Smiley)
|
||||
|
||||
* SOLR-11702: Redesign current LIR implementation (Cao Manh Dat, shalin)
|
||||
|
||||
|
|
|
@ -108,12 +108,12 @@ public class CreateAliasCmd implements OverseerCollectionMessageHandler.Cmd {
|
|||
+ " plus some create-collection prefixed ones.");
|
||||
}
|
||||
|
||||
Map<String, String> aliasMetadata = new LinkedHashMap<>();
|
||||
Map<String, String> aliasProperties = new LinkedHashMap<>();
|
||||
message.getProperties().entrySet().stream()
|
||||
.filter(entry -> TimeRoutedAlias.PARAM_IS_METADATA.test(entry.getKey()))
|
||||
.forEach(entry -> aliasMetadata.put(entry.getKey(), (String) entry.getValue())); // way easier than .collect
|
||||
.filter(entry -> TimeRoutedAlias.PARAM_IS_PROP.test(entry.getKey()))
|
||||
.forEach(entry -> aliasProperties.put(entry.getKey(), (String) entry.getValue())); // way easier than .collect
|
||||
|
||||
TimeRoutedAlias timeRoutedAlias = new TimeRoutedAlias(aliasName, aliasMetadata); // validates as well
|
||||
TimeRoutedAlias timeRoutedAlias = new TimeRoutedAlias(aliasName, aliasProperties); // validates as well
|
||||
|
||||
String start = message.getStr(TimeRoutedAlias.ROUTER_START);
|
||||
Instant startTime = parseStart(start, timeRoutedAlias.getTimeZone());
|
||||
|
@ -121,13 +121,13 @@ public class CreateAliasCmd implements OverseerCollectionMessageHandler.Cmd {
|
|||
String initialCollectionName = TimeRoutedAlias.formatCollectionNameFromInstant(aliasName, startTime);
|
||||
|
||||
// Create the collection
|
||||
MaintainRoutedAliasCmd.createCollectionAndWait(state, aliasName, aliasMetadata, initialCollectionName, ocmh);
|
||||
MaintainRoutedAliasCmd.createCollectionAndWait(state, aliasName, aliasProperties, initialCollectionName, ocmh);
|
||||
validateAllCollectionsExistAndNoDups(Collections.singletonList(initialCollectionName), zkStateReader);
|
||||
|
||||
// Create/update the alias
|
||||
zkStateReader.aliasesManager.applyModificationAndExportToZk(aliases -> aliases
|
||||
.cloneWithCollectionAlias(aliasName, initialCollectionName)
|
||||
.cloneWithCollectionAliasMetadata(aliasName, aliasMetadata));
|
||||
.cloneWithCollectionAliasProperties(aliasName, aliasProperties));
|
||||
}
|
||||
|
||||
private Instant parseStart(String str, TimeZone zone) {
|
||||
|
|
|
@ -103,7 +103,7 @@ public class MaintainRoutedAliasCmd implements OverseerCollectionMessageHandler.
|
|||
//---- PARSE ALIAS INFO FROM ZK
|
||||
final ZkStateReader.AliasesManager aliasesManager = ocmh.zkStateReader.aliasesManager;
|
||||
final Aliases aliases = aliasesManager.getAliases();
|
||||
final Map<String, String> aliasMetadata = aliases.getCollectionAliasMetadata(aliasName);
|
||||
final Map<String, String> aliasMetadata = aliases.getCollectionAliasProperties(aliasName);
|
||||
if (aliasMetadata == null) {
|
||||
throw newAliasMustExistException(aliasName); // if it did exist, we'd have a non-null map
|
||||
}
|
||||
|
|
|
@ -227,7 +227,7 @@ public class OverseerCollectionMessageHandler implements OverseerMessageHandler,
|
|||
.put(DELETE, new DeleteCollectionCmd(this))
|
||||
.put(CREATEALIAS, new CreateAliasCmd(this))
|
||||
.put(DELETEALIAS, new DeleteAliasCmd(this))
|
||||
.put(MODIFYALIAS, new ModifyAliasCmd(this))
|
||||
.put(ALIASPROP, new SetAliasPropCmd(this))
|
||||
.put(MAINTAINROUTEDALIAS, new MaintainRoutedAliasCmd(this))
|
||||
.put(OVERSEERSTATUS, new OverseerStatusCmd(this))
|
||||
.put(DELETESHARD, new DeleteShardCmd(this))
|
||||
|
|
|
@ -33,15 +33,15 @@ import static org.apache.solr.cloud.api.collections.OverseerCollectionMessageHan
|
|||
import static org.apache.solr.common.SolrException.ErrorCode.BAD_REQUEST;
|
||||
import static org.apache.solr.common.params.CommonParams.NAME;
|
||||
|
||||
public class ModifyAliasCmd implements Cmd {
|
||||
public class SetAliasPropCmd implements Cmd {
|
||||
|
||||
public static final String META_DATA = "metadata";
|
||||
public static final String PROPERTIES = "property";
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
private final OverseerCollectionMessageHandler messageHandler;
|
||||
|
||||
ModifyAliasCmd(OverseerCollectionMessageHandler messageHandler) {
|
||||
SetAliasPropCmd(OverseerCollectionMessageHandler messageHandler) {
|
||||
this.messageHandler = messageHandler;
|
||||
}
|
||||
|
||||
|
@ -58,22 +58,22 @@ public class ModifyAliasCmd implements Cmd {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> metadata = (Map<String, String>) message.get(META_DATA);
|
||||
Map<String, String> properties = (Map<String, String>) message.get(PROPERTIES);
|
||||
|
||||
zkStateReader.aliasesManager.applyModificationAndExportToZk(aliases1 -> {
|
||||
for (Map.Entry<String, String> entry : metadata.entrySet()) {
|
||||
for (Map.Entry<String, String> entry : properties.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if ("".equals(key.trim())) {
|
||||
throw new SolrException(BAD_REQUEST, "metadata keys must not be pure whitespace");
|
||||
throw new SolrException(BAD_REQUEST, "property keys must not be pure whitespace");
|
||||
}
|
||||
if (!key.equals(key.trim())) {
|
||||
throw new SolrException(BAD_REQUEST, "metadata keys should not begin or end with whitespace");
|
||||
throw new SolrException(BAD_REQUEST, "property keys should not begin or end with whitespace");
|
||||
}
|
||||
String value = entry.getValue();
|
||||
if ("".equals(value)) {
|
||||
value = null;
|
||||
}
|
||||
aliases1 = aliases1.cloneWithCollectionAliasMetadata(aliasName, key, value);
|
||||
aliases1 = aliases1.cloneWithCollectionAliasProperties(aliasName, key, value);
|
||||
}
|
||||
return aliases1;
|
||||
});
|
|
@ -84,7 +84,7 @@ public class TimeRoutedAlias {
|
|||
ROUTER_MAX_FUTURE,
|
||||
TZ)); // kinda special
|
||||
|
||||
static Predicate<String> PARAM_IS_METADATA =
|
||||
static Predicate<String> PARAM_IS_PROP =
|
||||
key -> key.equals(TZ) ||
|
||||
(key.startsWith(ROUTER_PREFIX) && !key.equals(ROUTER_START)) || //TODO reconsider START special case
|
||||
key.startsWith(CREATE_COLLECTION_PREFIX);
|
||||
|
|
|
@ -571,18 +571,18 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
|||
DELETEALIAS_OP(DELETEALIAS, (req, rsp, h) -> req.getParams().required().getAll(null, NAME)),
|
||||
|
||||
/**
|
||||
* Change metadata for an alias (use CREATEALIAS_OP to change the actual value of the alias)
|
||||
* Change properties for an alias (use CREATEALIAS_OP to change the actual value of the alias)
|
||||
*/
|
||||
MODIFYALIAS_OP(MODIFYALIAS, (req, rsp, h) -> {
|
||||
ALIASPROP_OP(ALIASPROP, (req, rsp, h) -> {
|
||||
Map<String, Object> params = req.getParams().required().getAll(null, NAME);
|
||||
|
||||
// Note: success/no-op in the event of no metadata supplied is intentional. Keeps code simple and one less case
|
||||
// Note: success/no-op in the event of no properties supplied is intentional. Keeps code simple and one less case
|
||||
// for api-callers to check for.
|
||||
return convertPrefixToMap(req.getParams(), params, "metadata");
|
||||
return convertPrefixToMap(req.getParams(), params, "property");
|
||||
}),
|
||||
|
||||
/**
|
||||
* List the aliases and associated metadata.
|
||||
* List the aliases and associated properties.
|
||||
*/
|
||||
LISTALIASES_OP(LISTALIASES, (req, rsp, h) -> {
|
||||
ZkStateReader zkStateReader = h.coreContainer.getZkController().getZkStateReader();
|
||||
|
@ -590,15 +590,15 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
|||
if (aliases != null) {
|
||||
// the aliases themselves...
|
||||
rsp.getValues().add("aliases", aliases.getCollectionAliasMap());
|
||||
// Any metadata for the above aliases.
|
||||
// Any properties for the above aliases.
|
||||
Map<String,Map<String,String>> meta = new LinkedHashMap<>();
|
||||
for (String alias : aliases.getCollectionAliasListMap().keySet()) {
|
||||
Map<String, String> collectionAliasMetadata = aliases.getCollectionAliasMetadata(alias);
|
||||
if (collectionAliasMetadata != null) {
|
||||
meta.put(alias, collectionAliasMetadata);
|
||||
Map<String, String> collectionAliasProperties = aliases.getCollectionAliasProperties(alias);
|
||||
if (collectionAliasProperties != null) {
|
||||
meta.put(alias, collectionAliasProperties);
|
||||
}
|
||||
}
|
||||
rsp.getValues().add("metadata", meta);
|
||||
rsp.getValues().add("properties", meta);
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
|
|
|
@ -63,7 +63,7 @@ import static org.apache.solr.update.processor.DistributingUpdateProcessorFactor
|
|||
* requests to create new collections on-demand.
|
||||
*
|
||||
* Depends on this core having a special core property that points to the alias name that this collection is a part of.
|
||||
* And further requires certain metadata on the Alias. Collections pointed to by the alias must be named for the alias
|
||||
* And further requires certain properties on the Alias. Collections pointed to by the alias must be named for the alias
|
||||
* plus underscored ('_') and a time stamp of ISO_DATE plus optionally _HH_mm_ss. These collections should not be
|
||||
* created by the user, but are created automatically by the time partitioning system.
|
||||
*
|
||||
|
@ -124,14 +124,14 @@ public class TimeRoutedAliasUpdateProcessor extends UpdateRequestProcessor {
|
|||
cmdDistrib = new SolrCmdDistributor(cc.getUpdateShardHandler());
|
||||
collHandler = cc.getCollectionsHandler();
|
||||
|
||||
final Map<String, String> aliasMetadata = zkController.getZkStateReader().getAliases().getCollectionAliasMetadata(aliasName);
|
||||
if (aliasMetadata == null) {
|
||||
final Map<String, String> aliasProperties = zkController.getZkStateReader().getAliases().getCollectionAliasProperties(aliasName);
|
||||
if (aliasProperties == null) {
|
||||
throw newAliasMustExistException(); // if it did exist, we'd have a non-null map
|
||||
}
|
||||
try {
|
||||
this.timeRoutedAlias = new TimeRoutedAlias(aliasName, aliasMetadata);
|
||||
this.timeRoutedAlias = new TimeRoutedAlias(aliasName, aliasProperties);
|
||||
} catch (Exception e) { // ensure we throw SERVER_ERROR not BAD_REQUEST at this stage
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Routed alias has invalid metadata: " + e, e);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Routed alias has invalid properties: " + e, e);
|
||||
}
|
||||
|
||||
ModifiableSolrParams outParams = new ModifiableSolrParams(req.getParams());
|
||||
|
@ -237,7 +237,7 @@ public class TimeRoutedAliasUpdateProcessor extends UpdateRequestProcessor {
|
|||
|
||||
/**
|
||||
* Ensure {@link #parsedCollectionsAliases} is up to date. If it was modified, return true.
|
||||
* Note that this will return true if some other alias was modified or if metadata was modified. These
|
||||
* Note that this will return true if some other alias was modified or if properties were modified. These
|
||||
* are spurious and the caller should be written to be tolerant of no material changes.
|
||||
*/
|
||||
private boolean updateParsedCollectionAliases() {
|
||||
|
|
|
@ -94,7 +94,7 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
|
|||
|
||||
@Test
|
||||
@BadApple(bugUrl="https://issues.apache.org/jira/browse/SOLR-12028")
|
||||
public void testMetadata() throws Exception {
|
||||
public void testProperties() throws Exception {
|
||||
CollectionAdminRequest.createCollection("collection1meta", "conf", 2, 1).process(cluster.getSolrClient());
|
||||
CollectionAdminRequest.createCollection("collection2meta", "conf", 1, 1).process(cluster.getSolrClient());
|
||||
waitForState("Expected collection1 to be created with 2 shards and 1 replica", "collection1meta", clusterShape(2, 1));
|
||||
|
@ -117,32 +117,32 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
|
|||
//noinspection unchecked
|
||||
assertTrue(((Map<String,Map<String,?>>)Utils.fromJSON(rawBytes)).get("collection").get("meta1") instanceof String);
|
||||
|
||||
// set metadata
|
||||
UnaryOperator<Aliases> op5 = a -> a.cloneWithCollectionAliasMetadata("meta1", "foo", "bar");
|
||||
// set properties
|
||||
UnaryOperator<Aliases> op5 = a -> a.cloneWithCollectionAliasProperties("meta1", "foo", "bar");
|
||||
aliasesManager.applyModificationAndExportToZk(op5);
|
||||
Map<String, String> meta = zkStateReader.getAliases().getCollectionAliasMetadata("meta1");
|
||||
Map<String, String> meta = zkStateReader.getAliases().getCollectionAliasProperties("meta1");
|
||||
assertNotNull(meta);
|
||||
assertTrue(meta.containsKey("foo"));
|
||||
assertEquals("bar", meta.get("foo"));
|
||||
|
||||
// set more metadata
|
||||
UnaryOperator<Aliases> op4 = a -> a.cloneWithCollectionAliasMetadata("meta1", "foobar", "bazbam");
|
||||
// set more properties
|
||||
UnaryOperator<Aliases> op4 = a -> a.cloneWithCollectionAliasProperties("meta1", "foobar", "bazbam");
|
||||
aliasesManager.applyModificationAndExportToZk(op4);
|
||||
meta = zkStateReader.getAliases().getCollectionAliasMetadata("meta1");
|
||||
meta = zkStateReader.getAliases().getCollectionAliasProperties("meta1");
|
||||
assertNotNull(meta);
|
||||
|
||||
// old metadata still there
|
||||
// old properties still there
|
||||
assertTrue(meta.containsKey("foo"));
|
||||
assertEquals("bar", meta.get("foo"));
|
||||
|
||||
// new metadata added
|
||||
// new properties added
|
||||
assertTrue(meta.containsKey("foobar"));
|
||||
assertEquals("bazbam", meta.get("foobar"));
|
||||
|
||||
// remove metadata
|
||||
UnaryOperator<Aliases> op3 = a -> a.cloneWithCollectionAliasMetadata("meta1", "foo", null);
|
||||
// remove properties
|
||||
UnaryOperator<Aliases> op3 = a -> a.cloneWithCollectionAliasProperties("meta1", "foo", null);
|
||||
aliasesManager.applyModificationAndExportToZk(op3);
|
||||
meta = zkStateReader.getAliases().getCollectionAliasMetadata("meta1");
|
||||
meta = zkStateReader.getAliases().getCollectionAliasProperties("meta1");
|
||||
assertNotNull(meta);
|
||||
|
||||
// verify key was removed
|
||||
|
@ -153,13 +153,13 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
|
|||
assertEquals("bazbam", meta.get("foobar"));
|
||||
|
||||
// removal of non existent key should succeed.
|
||||
UnaryOperator<Aliases> op2 = a -> a.cloneWithCollectionAliasMetadata("meta1", "foo", null);
|
||||
UnaryOperator<Aliases> op2 = a -> a.cloneWithCollectionAliasProperties("meta1", "foo", null);
|
||||
aliasesManager.applyModificationAndExportToZk(op2);
|
||||
|
||||
// chained invocations
|
||||
UnaryOperator<Aliases> op1 = a ->
|
||||
a.cloneWithCollectionAliasMetadata("meta1", "foo2", "bazbam")
|
||||
.cloneWithCollectionAliasMetadata("meta1", "foo3", "bazbam2");
|
||||
a.cloneWithCollectionAliasProperties("meta1", "foo2", "bazbam")
|
||||
.cloneWithCollectionAliasProperties("meta1", "foo3", "bazbam2");
|
||||
aliasesManager.applyModificationAndExportToZk(op1);
|
||||
|
||||
// some other independent update (not overwritten)
|
||||
|
@ -169,17 +169,17 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
|
|||
// competing went through
|
||||
assertEquals("collection1meta,collection2meta", zkStateReader.getAliases().getCollectionAliasMap().get("meta3"));
|
||||
|
||||
meta = zkStateReader.getAliases().getCollectionAliasMetadata("meta1");
|
||||
meta = zkStateReader.getAliases().getCollectionAliasProperties("meta1");
|
||||
assertNotNull(meta);
|
||||
|
||||
// old metadata still there
|
||||
// old properties still there
|
||||
assertTrue(meta.containsKey("foobar"));
|
||||
assertEquals("bazbam", meta.get("foobar"));
|
||||
|
||||
// competing update not overwritten
|
||||
assertEquals("collection1meta,collection2meta", zkStateReader.getAliases().getCollectionAliasMap().get("meta3"));
|
||||
|
||||
// new metadata added
|
||||
// new properties added
|
||||
assertTrue(meta.containsKey("foo2"));
|
||||
assertEquals("bazbam", meta.get("foo2"));
|
||||
assertTrue(meta.containsKey("foo3"));
|
||||
|
@ -197,7 +197,7 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
|
|||
createdZKSR = true;
|
||||
zkStateReader.createClusterStateWatchersAndUpdate();
|
||||
|
||||
meta = zkStateReader.getAliases().getCollectionAliasMetadata("meta1");
|
||||
meta = zkStateReader.getAliases().getCollectionAliasProperties("meta1");
|
||||
assertNotNull(meta);
|
||||
|
||||
// verify key was removed in independent view
|
||||
|
@ -209,7 +209,7 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
|
|||
|
||||
Aliases a = zkStateReader.getAliases();
|
||||
Aliases clone = a.cloneWithCollectionAlias("meta1", null);
|
||||
meta = clone.getCollectionAliasMetadata("meta1");
|
||||
meta = clone.getCollectionAliasProperties("meta1");
|
||||
assertEquals(0,meta.size());
|
||||
} finally {
|
||||
if (createdZKSR) {
|
||||
|
@ -218,16 +218,17 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testModifyMetadataV2() throws Exception {
|
||||
@Test
|
||||
public void testModifyPropertiesV2() throws Exception {
|
||||
final String aliasName = getTestName();
|
||||
ZkStateReader zkStateReader = createColectionsAndAlias(aliasName);
|
||||
final String baseUrl = cluster.getRandomJetty(random()).getBaseUrl().toString();
|
||||
//TODO fix Solr test infra so that this /____v2/ becomes /api/
|
||||
HttpPost post = new HttpPost(baseUrl + "/____v2/c");
|
||||
post.setEntity(new StringEntity("{\n" +
|
||||
"\"modify-alias\" : {\n" +
|
||||
"\"set-alias-property\" : {\n" +
|
||||
" \"name\": \"" + aliasName + "\",\n" +
|
||||
" \"metadata\" : {\n" +
|
||||
" \"properties\" : {\n" +
|
||||
" \"foo\": \"baz\",\n" +
|
||||
" \"bar\": \"bam\"\n" +
|
||||
" }\n" +
|
||||
|
@ -238,51 +239,52 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
|
|||
checkFooAndBarMeta(aliasName, zkStateReader);
|
||||
}
|
||||
|
||||
public void testModifyMetadataV1() throws Exception {
|
||||
@Test
|
||||
public void testModifyPropertiesV1() throws Exception {
|
||||
// note we don't use TZ in this test, thus it's UTC
|
||||
final String aliasName = getTestName();
|
||||
ZkStateReader zkStateReader = createColectionsAndAlias(aliasName);
|
||||
final String baseUrl = cluster.getRandomJetty(random()).getBaseUrl().toString();
|
||||
HttpGet get = new HttpGet(baseUrl + "/admin/collections?action=MODIFYALIAS" +
|
||||
HttpGet get = new HttpGet(baseUrl + "/admin/collections?action=ALIASPROP" +
|
||||
"&wt=xml" +
|
||||
"&name=" + aliasName +
|
||||
"&metadata.foo=baz" +
|
||||
"&metadata.bar=bam");
|
||||
"&property.foo=baz" +
|
||||
"&property.bar=bam");
|
||||
assertSuccess(get);
|
||||
checkFooAndBarMeta(aliasName, zkStateReader);
|
||||
}
|
||||
|
||||
@Test
|
||||
@BadApple(bugUrl="https://issues.apache.org/jira/browse/SOLR-12028")
|
||||
public void testModifyMetadataCAR() throws Exception {
|
||||
public void testModifyPropertiesCAR() throws Exception {
|
||||
// note we don't use TZ in this test, thus it's UTC
|
||||
final String aliasName = getTestName();
|
||||
ZkStateReader zkStateReader = createColectionsAndAlias(aliasName);
|
||||
CollectionAdminRequest.ModifyAlias modifyAlias = CollectionAdminRequest.modifyAlias(aliasName);
|
||||
modifyAlias.addMetadata("foo","baz");
|
||||
modifyAlias.addMetadata("bar","bam");
|
||||
modifyAlias.process(cluster.getSolrClient());
|
||||
CollectionAdminRequest.SetAliasProperty setAliasProperty = CollectionAdminRequest.setAliasProperty(aliasName);
|
||||
setAliasProperty.addProperty("foo","baz");
|
||||
setAliasProperty.addProperty("bar","bam");
|
||||
setAliasProperty.process(cluster.getSolrClient());
|
||||
checkFooAndBarMeta(aliasName, zkStateReader);
|
||||
|
||||
// now verify we can delete
|
||||
modifyAlias = CollectionAdminRequest.modifyAlias(aliasName);
|
||||
modifyAlias.addMetadata("foo","");
|
||||
modifyAlias.process(cluster.getSolrClient());
|
||||
modifyAlias = CollectionAdminRequest.modifyAlias(aliasName);
|
||||
modifyAlias.addMetadata("bar",null);
|
||||
modifyAlias.process(cluster.getSolrClient());
|
||||
modifyAlias = CollectionAdminRequest.modifyAlias(aliasName);
|
||||
setAliasProperty = CollectionAdminRequest.setAliasProperty(aliasName);
|
||||
setAliasProperty.addProperty("foo","");
|
||||
setAliasProperty.process(cluster.getSolrClient());
|
||||
setAliasProperty = CollectionAdminRequest.setAliasProperty(aliasName);
|
||||
setAliasProperty.addProperty("bar",null);
|
||||
setAliasProperty.process(cluster.getSolrClient());
|
||||
setAliasProperty = CollectionAdminRequest.setAliasProperty(aliasName);
|
||||
|
||||
// whitespace value
|
||||
modifyAlias.addMetadata("foo"," ");
|
||||
modifyAlias.process(cluster.getSolrClient());
|
||||
setAliasProperty.addProperty("foo"," ");
|
||||
setAliasProperty.process(cluster.getSolrClient());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void checkFooAndBarMeta(String aliasName, ZkStateReader zkStateReader) throws Exception {
|
||||
zkStateReader.aliasesManager.update(); // ensure our view is up to date
|
||||
Map<String, String> meta = zkStateReader.getAliases().getCollectionAliasMetadata(aliasName);
|
||||
Map<String, String> meta = zkStateReader.getAliases().getCollectionAliasProperties(aliasName);
|
||||
assertNotNull(meta);
|
||||
assertTrue(meta.containsKey("foo"));
|
||||
assertEquals("baz", meta.get("foo"));
|
||||
|
|
|
@ -169,7 +169,7 @@ public class CreateRoutedAliasTest extends SolrCloudTestCase {
|
|||
Aliases aliases = cluster.getSolrClient().getZkStateReader().getAliases();
|
||||
Map<String, String> collectionAliasMap = aliases.getCollectionAliasMap();
|
||||
assertEquals(initialCollectionName, collectionAliasMap.get(aliasName));
|
||||
Map<String, String> meta = aliases.getCollectionAliasMetadata(aliasName);
|
||||
Map<String, String> meta = aliases.getCollectionAliasProperties(aliasName);
|
||||
//System.err.println(new TreeMap(meta));
|
||||
assertEquals("evt_dt",meta.get("router.field"));
|
||||
assertEquals("_default",meta.get("create-collection.collection.configName"));
|
||||
|
@ -214,7 +214,7 @@ public class CreateRoutedAliasTest extends SolrCloudTestCase {
|
|||
Map<String, String> collectionAliasMap = aliases.getCollectionAliasMap();
|
||||
String alias = collectionAliasMap.get(aliasName);
|
||||
assertNotNull(alias);
|
||||
Map<String, String> meta = aliases.getCollectionAliasMetadata(aliasName);
|
||||
Map<String, String> meta = aliases.getCollectionAliasProperties(aliasName);
|
||||
assertNotNull(meta);
|
||||
assertEquals("evt_dt",meta.get("router.field"));
|
||||
assertEquals("_default",meta.get("create-collection.collection.configName"));
|
||||
|
|
|
@ -202,8 +202,8 @@ public class TimeRoutedAliasUpdateProcessorTest extends SolrCloudTestCase {
|
|||
|
||||
|
||||
// update metadata to auto-delete oldest collections
|
||||
CollectionAdminRequest.modifyAlias(alias)
|
||||
.addMetadata(TimeRoutedAlias.ROUTER_AUTO_DELETE_AGE, "-1DAY") // thus usually keep 2 collections of a day size
|
||||
CollectionAdminRequest.setAliasProperty(alias)
|
||||
.addProperty(TimeRoutedAlias.ROUTER_AUTO_DELETE_AGE, "-1DAY") // thus usually keep 2 collections of a day size
|
||||
.process(solrClient);
|
||||
|
||||
// add more docs, creating one new collection, but trigger ones prior to
|
||||
|
|
|
@ -521,7 +521,7 @@ the data to shards based on customer id. Such shards can be of any type (NRT, PU
|
|||
placement strategies may also be used.
|
||||
|
||||
The values supplied in this command for collection creation will be retained
|
||||
in alias metadata, and can be verified by inspecting `aliases.json` in ZooKeeper.
|
||||
in alias properties, and can be verified by inspecting `aliases.json` in ZooKeeper.
|
||||
|
||||
*NOTE:* Presently only updates are routed and queries are distributed to all collections in the alias, but future
|
||||
features may enable routing of the query to the single appropriate collection based on a special parameter or perhaps
|
||||
|
@ -559,7 +559,7 @@ just fine. This parameter is required.
|
|||
`TZ`::
|
||||
The timezone to be used when evaluating any date math in router.start or router.interval. This is equivalent to the
|
||||
same parameter supplied to search queries, but understand in this case it's persisted with most of the other parameters
|
||||
as alias metadata.
|
||||
as an alias property.
|
||||
+
|
||||
If GMT-4 is supplied for this value then a document dated 2018-01-14T21:00:00:01.2345Z would be stored in the
|
||||
myAlias_2018-01-15_01 collection (assuming an interval of +1HOUR).
|
||||
|
@ -740,7 +740,7 @@ http://localhost:8983/solr/admin/collections?action=LISTALIASES&wt=xml
|
|||
<str name="testalias1">collection1</str>
|
||||
<str name="testalias2">collection1,collection2</str>
|
||||
</lst>
|
||||
<lst name="metadata">
|
||||
<lst name="properties">
|
||||
<lst name="testalias1"/>
|
||||
<lst name="testalias2">
|
||||
<str name="someKey">someValue</str>
|
||||
|
@ -749,37 +749,39 @@ http://localhost:8983/solr/admin/collections?action=LISTALIASES&wt=xml
|
|||
</response>
|
||||
----
|
||||
|
||||
[[modifyalias]]
|
||||
== MODIFYALIAS: Modify Alias Metadata for a Collection
|
||||
[[aliasprop]]
|
||||
== ALIASPROP: Modify Alias Properties for a Collection
|
||||
|
||||
The `MODIFYALIAS` action modifies the metadata on an alias. If a key is set with a value that is empty it will be removed.
|
||||
The `ALIASPROP` action modifies the properties (metadata) on an alias. If a key is set with a value that is empty it will be removed.
|
||||
|
||||
`/admin/collections?action=MODIFYALIAS&name=_name_&metadata.someKey=somevalue`
|
||||
`/admin/collections?action=ALIASPROP&name=_name_&property.someKey=somevalue`
|
||||
|
||||
=== MODIFYALIAS Parameters
|
||||
=== ALIASPROP Parameters
|
||||
|
||||
`name`::
|
||||
The alias name on which to set metadata. This parameter is required.
|
||||
The alias name on which to set properties. This parameter is required.
|
||||
|
||||
`metadata.*`::
|
||||
The name of the key for the metadata element to be modified replaces '*', the value for the parameter is passed as the value for the metadata.
|
||||
`property.*`::
|
||||
The name of the property to be modified replaces '*', the value for the parameter is passed as the value for the property.
|
||||
|
||||
`async`::
|
||||
Request ID to track this action which will be <<Asynchronous Calls,processed asynchronously>>.
|
||||
|
||||
=== MODIFYALIAS Response
|
||||
=== ALIASPROP Response
|
||||
|
||||
The output will simply be a responseHeader with details of the time it took to process the request. To confirm the creation of the metadata, you can look in the Solr Admin UI, under the Cloud section and find the `aliases.json` file or use the LISTALIASES api command.
|
||||
The output will simply be a responseHeader with details of the time it took to process the request.
|
||||
To confirm the creation of the property or properties, you can look in the Solr Admin UI, under the Cloud section and
|
||||
find the `aliases.json` file or use the LISTALIASES api command.
|
||||
|
||||
=== Examples using MODIFYALIAS
|
||||
=== Examples using ALIASPROP
|
||||
|
||||
*Input*
|
||||
|
||||
For an alias named "testalias2" and set the value "someValue" for a metadata key of "someKey" and "otherValue" for "otherKey".
|
||||
For an alias named "testalias2" and set the value "someValue" for a property of "someKey" and "otherValue" for "otherKey".
|
||||
|
||||
[source,text]
|
||||
----
|
||||
http://localhost:8983/solr/admin/collections?action=MODIFYALIAS&name=testalias2&metadata.someKey=someValue&metadata.otherKey=otherValue&wt=xml
|
||||
http://localhost:8983/solr/admin/collections?action=ALIASPROP&name=testalias2&property.someKey=someValue&property.otherKey=otherValue&wt=xml
|
||||
----
|
||||
|
||||
*Output*
|
||||
|
@ -809,7 +811,9 @@ Request ID to track this action which will be <<Asynchronous Calls,processed asy
|
|||
|
||||
=== DELETEALIAS Response
|
||||
|
||||
The output will simply be a responseHeader with details of the time it took to process the request. To confirm the removal of the alias, you can look in the Solr Admin UI, under the Cloud section, and find the `aliases.json` file.
|
||||
The output will simply be a responseHeader with details of the time it took to process the request.
|
||||
To confirm the removal of the alias, you can look in the Solr Admin UI, under the Cloud section, and
|
||||
find the `aliases.json` file.
|
||||
|
||||
=== Examples using DELETEALIAS
|
||||
|
||||
|
|
|
@ -1320,29 +1320,29 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
|
|||
|
||||
}
|
||||
|
||||
// MODIFYALIAS request
|
||||
// ALIASPROP request
|
||||
|
||||
/**
|
||||
* Returns a SolrRequest to add or remove metadata from a request
|
||||
* Returns a SolrRequest to add or remove properties from an alias
|
||||
* @param aliasName the alias to modify
|
||||
*/
|
||||
|
||||
public static ModifyAlias modifyAlias(String aliasName) {
|
||||
return new ModifyAlias(aliasName);
|
||||
public static SetAliasProperty setAliasProperty(String aliasName) {
|
||||
return new SetAliasProperty(aliasName);
|
||||
}
|
||||
|
||||
public static class ModifyAlias extends AsyncCollectionAdminRequest {
|
||||
public static class SetAliasProperty extends AsyncCollectionAdminRequest {
|
||||
|
||||
private final String aliasName;
|
||||
private Map<String,String> metadata = new HashMap<>();
|
||||
private Map<String,String> properties = new HashMap<>();
|
||||
|
||||
public ModifyAlias(String aliasName) {
|
||||
super(CollectionAction.MODIFYALIAS);
|
||||
public SetAliasProperty(String aliasName) {
|
||||
super(CollectionAction.ALIASPROP);
|
||||
this.aliasName = SolrIdentifierValidator.validateAliasName(aliasName);
|
||||
}
|
||||
|
||||
public ModifyAlias addMetadata(String key, String value) {
|
||||
metadata.put(key,value);
|
||||
public SetAliasProperty addProperty(String key, String value) {
|
||||
properties.put(key,value);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1350,7 +1350,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
|
|||
public SolrParams getParams() {
|
||||
ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
|
||||
params.set(CoreAdminParams.NAME, aliasName);
|
||||
metadata.forEach((key, value) -> params.set("metadata." + key, value));
|
||||
properties.forEach((key, value) -> params.set("property." + key, value));
|
||||
return params;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,11 +129,12 @@ public class CollectionApiMapping {
|
|||
DELETEALIAS,
|
||||
"delete-alias",
|
||||
null),
|
||||
MODIFY_ALIAS(COLLECTIONS_COMMANDS,
|
||||
ALIAS_PROP(COLLECTIONS_COMMANDS,
|
||||
POST,
|
||||
MODIFYALIAS,
|
||||
"modify-alias",
|
||||
null),
|
||||
ALIASPROP,
|
||||
"set-alias-property",
|
||||
null,
|
||||
Utils.makeMap("property.", "properties.")),
|
||||
CREATE_SHARD(PER_COLLECTION_SHARDS_COMMANDS,
|
||||
POST,
|
||||
CREATESHARD,
|
||||
|
|
|
@ -44,24 +44,28 @@ public class Aliases {
|
|||
*/
|
||||
public static final Aliases EMPTY = new Aliases(Collections.emptyMap(), Collections.emptyMap(), 0);
|
||||
|
||||
// These two constants correspond to the top level elements in aliases.json. The first one denotes
|
||||
// a section containing a list of aliases and their attendant collections, the second contains a list of
|
||||
// aliases and their attendant properties (metadata) They probably should be
|
||||
// named "aliases" and "alias_properties" but for back compat reasons, we cannot change them
|
||||
private static final String COLLECTION = "collection";
|
||||
private static final String COLLECTION_METADATA = "collection_metadata";
|
||||
|
||||
// aliasName -> list of collections. (note: the Lists here should be unmodifiable)
|
||||
private final Map<String, List<String>> collectionAliases; // not null
|
||||
|
||||
// aliasName --> metadataKey --> metadataValue (note: the inner Map here should be unmodifiable)
|
||||
private final Map<String, Map<String, String>> collectionAliasMetadata; // notnull
|
||||
// aliasName --> propertiesKey --> propertiesValue (note: the inner Map here should be unmodifiable)
|
||||
private final Map<String, Map<String, String>> collectionAliasProperties; // notnull
|
||||
|
||||
private final int zNodeVersion;
|
||||
|
||||
/** Construct aliases directly with this information -- caller should not retain.
|
||||
* Any deeply nested collections are assumed to already be unmodifiable. */
|
||||
private Aliases(Map<String, List<String>> collectionAliases,
|
||||
Map<String, Map<String, String>> collectionAliasMetadata,
|
||||
Map<String, Map<String, String>> collectionAliasProperties,
|
||||
int zNodeVersion) {
|
||||
this.collectionAliases = Objects.requireNonNull(collectionAliases);
|
||||
this.collectionAliasMetadata = Objects.requireNonNull(collectionAliasMetadata);
|
||||
this.collectionAliasProperties = Objects.requireNonNull(collectionAliasProperties);
|
||||
this.zNodeVersion = zNodeVersion;
|
||||
}
|
||||
|
||||
|
@ -96,13 +100,13 @@ public class Aliases {
|
|||
*/
|
||||
public byte[] toJSON() {
|
||||
if (collectionAliases.isEmpty()) {
|
||||
assert collectionAliasMetadata.isEmpty();
|
||||
assert collectionAliasProperties.isEmpty();
|
||||
return null;
|
||||
} else {
|
||||
Map<String,Map> tmp = new LinkedHashMap<>();
|
||||
tmp.put(COLLECTION, convertMapOfListToMapOfCommaDelimited(collectionAliases));
|
||||
if (!collectionAliasMetadata.isEmpty()) {
|
||||
tmp.put(COLLECTION_METADATA, collectionAliasMetadata);
|
||||
if (!collectionAliasProperties.isEmpty()) {
|
||||
tmp.put(COLLECTION_METADATA, collectionAliasProperties);
|
||||
}
|
||||
return Utils.toJSON(tmp);
|
||||
}
|
||||
|
@ -154,15 +158,15 @@ public class Aliases {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable Map of metadata for a given alias. If an alias by the given name
|
||||
* Returns an unmodifiable Map of properties for a given alias. If an alias by the given name
|
||||
* exists, this method will never return null.
|
||||
*
|
||||
* @param alias the name of an alias also found as a key in {@link #getCollectionAliasListMap()}
|
||||
* @return The metadata for the alias (possibly empty) or null if the alias does not exist.
|
||||
* @return The properties for the alias (possibly empty) or null if the alias does not exist.
|
||||
*/
|
||||
public Map<String,String> getCollectionAliasMetadata(String alias) {
|
||||
public Map<String,String> getCollectionAliasProperties(String alias) {
|
||||
// Note: map is already unmodifiable; it can be shared safely
|
||||
return collectionAliasMetadata.getOrDefault(alias, Collections.emptyMap());
|
||||
return collectionAliasProperties.getOrDefault(alias, Collections.emptyMap());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,72 +216,72 @@ public class Aliases {
|
|||
if (alias == null) {
|
||||
throw new NullPointerException("Alias name cannot be null");
|
||||
}
|
||||
Map<String, Map<String, String>> newColMetadata;
|
||||
Map<String, Map<String, String>> newColProperties;
|
||||
Map<String, List<String>> newColAliases = new LinkedHashMap<>(this.collectionAliases);//clone to modify
|
||||
if (collections == null) { // REMOVE:
|
||||
newColMetadata = new LinkedHashMap<>(this.collectionAliasMetadata);//clone to modify
|
||||
newColMetadata.remove(alias);
|
||||
newColProperties = new LinkedHashMap<>(this.collectionAliasProperties);//clone to modify
|
||||
newColProperties.remove(alias);
|
||||
newColAliases.remove(alias);
|
||||
} else {
|
||||
newColMetadata = this.collectionAliasMetadata;// no changes
|
||||
newColProperties = this.collectionAliasProperties;// no changes
|
||||
// java representation is a list, so split before adding to maintain consistency
|
||||
newColAliases.put(alias, splitCollections(collections)); // note: unmodifiableList
|
||||
}
|
||||
return new Aliases(newColAliases, newColMetadata, zNodeVersion);
|
||||
return new Aliases(newColAliases, newColProperties, zNodeVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value for some metadata on a collection alias. This is done by creating a new Aliases instance
|
||||
* Set the value for some properties on a collection alias. This is done by creating a new Aliases instance
|
||||
* with the same data as the current one but with a modification based on the parameters.
|
||||
* <p>
|
||||
* Note that the state in zookeeper is unaffected by this method and the change must still be persisted via
|
||||
* {@link ZkStateReader.AliasesManager#applyModificationAndExportToZk(UnaryOperator)}
|
||||
*
|
||||
* @param alias the alias to update
|
||||
* @param metadataKey the key for the metadata
|
||||
* @param metadataValue the metadata to add/replace, null to remove the key.
|
||||
* @return An immutable copy of the aliases with the new metadata.
|
||||
* @param propertiesKey the key for the properties
|
||||
* @param propertiesValue the properties to add/replace, null to remove the key.
|
||||
* @return An immutable copy of the aliases with the new properties.
|
||||
*/
|
||||
public Aliases cloneWithCollectionAliasMetadata(String alias, String metadataKey, String metadataValue) {
|
||||
return cloneWithCollectionAliasMetadata(alias, Collections.singletonMap(metadataKey,metadataValue));
|
||||
public Aliases cloneWithCollectionAliasProperties(String alias, String propertiesKey, String propertiesValue) {
|
||||
return cloneWithCollectionAliasProperties(alias, Collections.singletonMap(propertiesKey,propertiesValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the values for some metadata keys on a collection alias. This is done by creating a new Aliases instance
|
||||
* Set the values for some properties keys on a collection alias. This is done by creating a new Aliases instance
|
||||
* with the same data as the current one but with a modification based on the parameters.
|
||||
* <p>
|
||||
* Note that the state in zookeeper is unaffected by this method and the change must still be persisted via
|
||||
* {@link ZkStateReader.AliasesManager#applyModificationAndExportToZk(UnaryOperator)}
|
||||
*
|
||||
* @param alias the alias to update
|
||||
* @param metadata the metadata to add/replace, null values in the map will remove the key.
|
||||
* @return An immutable copy of the aliases with the new metadata.
|
||||
* @param properties the properties to add/replace, null values in the map will remove the key.
|
||||
* @return An immutable copy of the aliases with the new properties.
|
||||
*/
|
||||
public Aliases cloneWithCollectionAliasMetadata(String alias, Map<String,String> metadata) {
|
||||
public Aliases cloneWithCollectionAliasProperties(String alias, Map<String,String> properties) {
|
||||
if (!collectionAliases.containsKey(alias)) {
|
||||
throw new IllegalArgumentException(alias + " is not a valid alias");
|
||||
}
|
||||
if (metadata == null) {
|
||||
throw new IllegalArgumentException("Null is not a valid metadata map");
|
||||
if (properties == null) {
|
||||
throw new IllegalArgumentException("Null is not a valid properties map");
|
||||
}
|
||||
Map<String,Map<String,String>> newColMetadata = new LinkedHashMap<>(this.collectionAliasMetadata);//clone to modify
|
||||
Map<String, String> newMetaMap = new LinkedHashMap<>(newColMetadata.getOrDefault(alias, Collections.emptyMap()));
|
||||
for (Map.Entry<String, String> metaEntry : metadata.entrySet()) {
|
||||
Map<String,Map<String,String>> newColProperties = new LinkedHashMap<>(this.collectionAliasProperties);//clone to modify
|
||||
Map<String, String> newMetaMap = new LinkedHashMap<>(newColProperties.getOrDefault(alias, Collections.emptyMap()));
|
||||
for (Map.Entry<String, String> metaEntry : properties.entrySet()) {
|
||||
if (metaEntry.getValue() != null) {
|
||||
newMetaMap.put(metaEntry.getKey(), metaEntry.getValue());
|
||||
} else {
|
||||
newMetaMap.remove(metaEntry.getKey());
|
||||
}
|
||||
}
|
||||
newColMetadata.put(alias, Collections.unmodifiableMap(newMetaMap));
|
||||
return new Aliases(collectionAliases, newColMetadata, zNodeVersion);
|
||||
newColProperties.put(alias, Collections.unmodifiableMap(newMetaMap));
|
||||
return new Aliases(collectionAliases, newColProperties, zNodeVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Aliases{" +
|
||||
"collectionAliases=" + collectionAliases +
|
||||
", collectionAliasMetadata=" + collectionAliasMetadata +
|
||||
", collectionAliasProperties=" + collectionAliasProperties +
|
||||
", zNodeVersion=" + zNodeVersion +
|
||||
'}';
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public interface CollectionParams {
|
|||
SYNCSHARD(true, LockLevel.SHARD),
|
||||
CREATEALIAS(true, LockLevel.COLLECTION),
|
||||
DELETEALIAS(true, LockLevel.COLLECTION),
|
||||
MODIFYALIAS(true, LockLevel.COLLECTION),
|
||||
ALIASPROP(true, LockLevel.COLLECTION),
|
||||
LISTALIASES(false, LockLevel.NONE),
|
||||
MAINTAINROUTEDALIAS(true, LockLevel.COLLECTION),
|
||||
DELETEROUTEDALIASCOLLECTIONS(true, LockLevel.COLLECTION),
|
||||
|
|
|
@ -210,18 +210,18 @@
|
|||
"name"
|
||||
]
|
||||
},
|
||||
"modify-alias": {
|
||||
"set-alias-property": {
|
||||
"documentation": "https://lucene.apache.org/solr/guide/collections-api.html#modifyalias",
|
||||
"description": "Allows changing the metadata on an alias. If a key is set with an empty string then it will be removed",
|
||||
"description": "Allows changing the properties on an alias. If a key is set with an empty string then it will be removed",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The alias name on which to set metadata."
|
||||
"description": "The alias name on which to set properties."
|
||||
},
|
||||
"metadata" : {
|
||||
"properties" : {
|
||||
"type": "object",
|
||||
"description": "A map of key/value pairs that will be associated with the alias as alias metadata. An empty value will delete any existing value for a given key.",
|
||||
"description": "A map of key/value pairs that will be associated with the alias as alias properties (metadata). An empty value will delete any existing value for a given key.",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"async": {
|
||||
|
|
Loading…
Reference in New Issue