blob: 17f00b18c99142d247c7e2753d5f0aea1d576a6f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.apache.hugegraph.api;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.apache.hugegraph.exception.NotSupportException;
import org.apache.hugegraph.exception.ServerException;
import org.apache.hugegraph.structure.Task;
import org.apache.hugegraph.structure.constant.HugeType;
import org.apache.hugegraph.structure.constant.IndexType;
import org.apache.hugegraph.structure.graph.Vertex;
import org.apache.hugegraph.structure.schema.IndexLabel;
import org.apache.hugegraph.testutil.Assert;
import org.apache.hugegraph.testutil.Utils;
import org.apache.hugegraph.util.DateUtil;
import org.apache.hugegraph.util.VersionUtil;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
public class IndexLabelApiTest extends BaseApiTest {
private static final Function<String, IndexLabel> fillIndexLabel =
(name) -> schema().indexLabel(name)
.onV("person")
.by("age")
.range()
.build();
@BeforeClass
public static void prepareSchema() {
BaseApiTest.initPropertyKey();
BaseApiTest.initVertexLabel();
BaseApiTest.initEdgeLabel();
}
@Override
@After
public void teardown() throws Exception {
List<Long> taskIds = new ArrayList<>();
indexLabelAPI.list().forEach(il -> {
taskIds.add(indexLabelAPI.delete(il.name()));
});
taskIds.forEach(BaseApiTest::waitUntilTaskCompleted);
}
@Test
public void testCreate() {
IndexLabel indexLabel = indexLabelAPI.create(fillIndexLabel.apply("personByAge"))
.indexLabel();
Assert.assertEquals("personByAge", indexLabel.name());
Assert.assertEquals(HugeType.VERTEX_LABEL, indexLabel.baseType());
Assert.assertEquals("person", indexLabel.baseValue());
Assert.assertEquals(IndexType.RANGE, indexLabel.indexType());
List<String> fields = ImmutableList.of("age");
Assert.assertEquals(fields.size(), indexLabel.indexFields().size());
Assert.assertTrue(fields.containsAll(indexLabel.indexFields()));
}
@Test
public void testCreateWithIndexType() {
IndexLabel indexLabel = schema().indexLabel("personByAge")
.onV("person")
.by("age")
.indexType(IndexType.RANGE)
.build();
Assert.assertEquals("personByAge", indexLabel.name());
Assert.assertEquals(HugeType.VERTEX_LABEL, indexLabel.baseType());
Assert.assertEquals("person", indexLabel.baseValue());
Assert.assertEquals(IndexType.RANGE, indexLabel.indexType());
List<String> fields = ImmutableList.of("age");
Assert.assertEquals(fields.size(), indexLabel.indexFields().size());
Assert.assertTrue(fields.containsAll(indexLabel.indexFields()));
}
@Test
public void testCreateWithInvalidName() {
Utils.assertResponseError(400, () -> {
indexLabelAPI.create(fillIndexLabel.apply(""));
});
Utils.assertResponseError(400, () -> {
indexLabelAPI.create(fillIndexLabel.apply(" "));
});
Utils.assertResponseError(400, () -> {
indexLabelAPI.create(fillIndexLabel.apply(" "));
});
}
@Test
public void testCreateExistedIndexLabel() {
indexLabelAPI.create(fillIndexLabel.apply("personByAge"));
Utils.assertResponseError(400, () -> {
indexLabelAPI.create(fillIndexLabel.apply("personByAge"));
});
}
@Test
public void testCreateOnUndefinedSchemaLabel() {
IndexLabel indexLabel1 = schema().indexLabel("authorByAge")
.onV("author")
.by("age")
.range()
.build();
Utils.assertResponseError(400, () -> {
indexLabelAPI.create(indexLabel1);
});
IndexLabel indexLabel2 = schema().indexLabel("writeByDate")
.onE("write")
.by("date")
.secondary()
.build();
Utils.assertResponseError(400, () -> {
indexLabelAPI.create(indexLabel2);
});
}
@Test
public void testCreateSearchIndexOnMultiProperties() {
IndexLabel indexLabel = schema().indexLabel("personByAgeAndCity")
.onV("person")
.by("age", "city")
.search()
.build();
Utils.assertResponseError(400, () -> {
indexLabelAPI.create(indexLabel);
});
}
@Test
public void testCreateSecondaryIndexOnMultiPropertiesOverrideExist() {
String personByCity = "personByCity";
String personByCityAndAge = "personByCityAndAge";
schema().indexLabel("personByCity")
.onV("person")
.by("city")
.secondary()
.create();
indexLabelAPI.get(personByCity);
Assert.assertThrows(ServerException.class, () -> {
indexLabelAPI.get(personByCityAndAge);
}, e -> {
String expect = String.format("index label with name '%s' does " +
"not exist", personByCityAndAge);
Assert.assertContains(expect, e.getMessage());
});
schema().indexLabel(personByCityAndAge)
.onV("person")
.by("city", "age")
.secondary()
.create();
Assert.assertThrows(ServerException.class, () -> {
indexLabelAPI.get(personByCity);
}, e -> {
String expect = String.format("index label with name '%s' does " +
"not exist", personByCity);
Assert.assertContains(expect, e.getMessage());
});
indexLabelAPI.get(personByCityAndAge);
}
@Test
public void testCreateShardIndexOnMultiPropertiesOverrideExist() {
String personByCity = "personByCity";
String personByCityAndAge = "personByCityAndAge";
schema().indexLabel(personByCity)
.onV("person")
.by("city")
.secondary()
.create();
indexLabelAPI.get(personByCity);
Assert.assertThrows(ServerException.class, () -> {
indexLabelAPI.get(personByCityAndAge);
}, e -> {
String expect = String.format("index label with name '%s' does " +
"not exist", personByCityAndAge);
Assert.assertContains(expect, e.getMessage());
});
schema().indexLabel(personByCityAndAge)
.onV("person")
.by("city", "age")
.shard()
.create();
Assert.assertThrows(ServerException.class, () -> {
indexLabelAPI.get(personByCity);
}, e -> {
String expect = String.format("index label with name '%s' does " +
"not exist", personByCity);
Assert.assertContains(expect, e.getMessage());
});
indexLabelAPI.get(personByCityAndAge);
}
@Test
public void testCreateRangeIndexOnNotNumberProperty() {
IndexLabel indexLabel = schema().indexLabel("personByCity")
.onV("person")
.by("city")
.range()
.build();
Utils.assertResponseError(400, () -> {
indexLabelAPI.create(indexLabel);
});
}
@Test
public void testCreateUniqueIndex() {
IndexLabel indexLabel = schema().indexLabel("personByCity")
.onV("person")
.by("city")
.unique()
.create();
Assert.assertEquals("personByCity", indexLabel.name());
Assert.assertEquals(HugeType.VERTEX_LABEL, indexLabel.baseType());
Assert.assertEquals("person", indexLabel.baseValue());
Assert.assertEquals(IndexType.UNIQUE, indexLabel.indexType());
List<String> fields = ImmutableList.of("city");
Assert.assertEquals(fields.size(), indexLabel.indexFields().size());
Assert.assertTrue(fields.containsAll(indexLabel.indexFields()));
}
@Test
public void testGet() {
IndexLabel indexLabel1 = schema().indexLabel("personByAge")
.onV("person")
.by("age")
.range()
.build();
indexLabel1 = indexLabelAPI.create(indexLabel1).indexLabel();
IndexLabel indexLabel2 = indexLabelAPI.get("personByAge");
Assert.assertEquals(indexLabel1.name(), indexLabel2.name());
Assert.assertEquals(indexLabel1.baseType(), indexLabel2.baseType());
Assert.assertEquals(indexLabel1.baseValue(), indexLabel2.baseValue());
Assert.assertEquals(indexLabel1.indexType(), indexLabel2.indexType());
Assert.assertEquals(indexLabel1.indexFields(),
indexLabel2.indexFields());
}
@Test
public void testGetNotExist() {
Utils.assertResponseError(404, () -> {
indexLabelAPI.get("not-exist-il");
});
}
@Test
public void testList() {
IndexLabel indexLabel1 = indexLabelAPI.create(fillIndexLabel.apply("personByAge"))
.indexLabel();
IndexLabel indexLabel2 = schema().indexLabel("personByCity")
.onV("person")
.by("city")
.secondary()
.build();
indexLabel2 = indexLabelAPI.create(indexLabel2).indexLabel();
List<IndexLabel> indexLabels = indexLabelAPI.list();
Assert.assertEquals(2, indexLabels.size());
assertContains(indexLabels, indexLabel1);
assertContains(indexLabels, indexLabel2);
}
@Test
public void testListByNames() {
IndexLabel personByAge = fillIndexLabel.apply("personByAge");
personByAge = indexLabelAPI.create(personByAge).indexLabel();
IndexLabel personByCity = schema().indexLabel("personByCity")
.onV("person")
.by("city")
.secondary()
.build();
personByCity = indexLabelAPI.create(personByCity).indexLabel();
List<IndexLabel> indexLabels;
indexLabels = indexLabelAPI.list(ImmutableList.of("personByAge"));
Assert.assertEquals(1, indexLabels.size());
assertContains(indexLabels, personByAge);
indexLabels = indexLabelAPI.list(ImmutableList.of("personByCity"));
Assert.assertEquals(1, indexLabels.size());
assertContains(indexLabels, personByCity);
indexLabels = indexLabelAPI.list(ImmutableList.of("personByAge",
"personByCity"));
Assert.assertEquals(2, indexLabels.size());
assertContains(indexLabels, personByAge);
assertContains(indexLabels, personByCity);
}
@Test
public void testDelete() {
String name = "personByAge";
indexLabelAPI.create(fillIndexLabel.apply(name));
long taskId = indexLabelAPI.delete(name);
waitUntilTaskCompleted(taskId);
Assert.assertThrows(ServerException.class, () -> {
indexLabelAPI.get(name);
}, e -> {
String expect = String.format("index label with name '%s' does " +
"not exist", name);
Assert.assertContains(expect, e.getMessage());
});
}
@Test
public void testDeleteNotExist() {
Utils.assertResponseError(404, () -> {
indexLabelAPI.delete("not-exist-il");
});
}
@Test
public void testAddIndexLabelWithUserData() {
IndexLabel personByAge = schema().indexLabel("personByAge")
.onV("person")
.by("age")
.range()
.userdata("min", 0)
.userdata("max", 100)
.build();
personByAge = indexLabelAPI.create(personByAge).indexLabel();
Assert.assertEquals(3, personByAge.userdata().size());
Assert.assertEquals(0, personByAge.userdata().get("min"));
Assert.assertEquals(100, personByAge.userdata().get("max"));
String time = (String) personByAge.userdata().get("~create_time");
Date createTime = DateUtil.parse(time);
Utils.assertBeforeNow(createTime);
IndexLabel personByCity = schema().indexLabel("personByCity")
.onV("person")
.by("city")
.secondary()
.userdata("length", 15)
.userdata("length", 18)
.build();
personByCity = indexLabelAPI.create(personByCity).indexLabel();
// The same key user data will be overwritten
Assert.assertEquals(2, personByCity.userdata().size());
Assert.assertEquals(18, personByCity.userdata().get("length"));
time = (String) personByCity.userdata().get("~create_time");
createTime = DateUtil.parse(time);
Utils.assertBeforeNow(createTime);
IndexLabel bookByName = schema().indexLabel("bookByName")
.onV("book")
.by("name")
.secondary()
.userdata("option",
ImmutableList.of("xx", "yy"))
.build();
bookByName = indexLabelAPI.create(bookByName).indexLabel();
Assert.assertEquals(2, bookByName.userdata().size());
Assert.assertEquals(ImmutableList.of("xx", "yy"),
bookByName.userdata().get("option"));
time = (String) bookByName.userdata().get("~create_time");
createTime = DateUtil.parse(time);
Utils.assertBeforeNow(createTime);
}
@Test
public void testAddIndexLabelWithUserDataWithApiVersion49() {
VersionUtil.Version originApiVersion = client().apiVersion();
VersionUtil.Version apiVersion = VersionUtil.Version.of("0.49");
client().apiVersion(apiVersion);
IndexLabel personByAge = schema().indexLabel("personByAge")
.onV("person")
.by("age")
.range()
.build();
personByAge = indexLabelAPI.create(personByAge).indexLabel();
Assert.assertEquals(1, personByAge.userdata().size());
IndexLabel personByAge1 = schema().indexLabel("personByAge1")
.onV("person")
.by("age")
.range()
.userdata("min", 0)
.userdata("max", 100)
.build();
Assert.assertThrows(IllegalArgumentException.class, () -> {
indexLabelAPI.create(personByAge1).indexLabel();
}, (e) -> {
String msg = "Not support userdata of index label until api " +
"version 0.50";
Assert.assertContains(msg, e.getMessage());
});
IndexLabel personByAge2 = schema().indexLabel("personByAge2")
.onV("person")
.by("age")
.userdata("min", 0)
.build();
Assert.assertThrows(NotSupportException.class, () -> {
indexLabelAPI.append(personByAge2);
}, (e) -> {
Assert.assertContains("action append on index label",
e.getMessage());
});
IndexLabel personByAge3 = schema().indexLabel("personByAge3")
.onV("person")
.by("age")
.userdata("min", 0)
.build();
Assert.assertThrows(NotSupportException.class, () -> {
indexLabelAPI.eliminate(personByAge3);
}, (e) -> {
Assert.assertContains("action eliminate on index label",
e.getMessage());
});
client().apiVersion(originApiVersion);
}
@Test
public void testAddIndexLabelWithRebuildFalse() {
Vertex vertex = new Vertex("person");
vertex.property("name", "James");
vertex.property("city", "Beijing");
vertex.property("age", 19);
vertex = vertexAPI.create(vertex);
IndexLabel personByAge = schema().indexLabel("personByAge")
.onV("person")
.by("city")
.secondary()
.rebuild(false)
.build();
IndexLabel.IndexLabelWithTask il = indexLabelAPI.create(personByAge);
IndexLabel created = il.indexLabel();
Assert.assertEquals(personByAge.name(), created.name());
Assert.assertEquals(personByAge.baseType(), created.baseType());
Assert.assertEquals(personByAge.baseValue(), created.baseValue());
Assert.assertEquals(personByAge.indexType(), created.indexType());
Assert.assertEquals(Task.TASK_ID_NULL, il.taskId());
Map<String, Object> properties = ImmutableMap.of("city", "Beijing");
List<Vertex> vertices = vertexAPI.list("person", properties, 0,
null, 10).results();
Assert.assertEquals(0, vertices.size());
long taskId = rebuildAPI.rebuild(personByAge);
waitUntilTaskCompleted(taskId);
vertices = vertexAPI.list("person", properties, 0, null, 10)
.results();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(vertex, vertices.get(0));
}
}