Skip to content

Commit 79a682c

Browse files
committed
#80 reduce ensure index calls (ignore hash and skiplist index as they will be removed with driver 7)
1 parent 817b6d7 commit 79a682c

File tree

1 file changed

+102
-36
lines changed

1 file changed

+102
-36
lines changed

src/main/java/com/arangodb/springframework/core/template/ArangoTemplate.java

Lines changed: 102 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
import org.springframework.expression.ParserContext;
5454
import org.springframework.expression.spel.standard.SpelExpressionParser;
5555
import org.springframework.expression.spel.support.StandardEvaluationContext;
56+
import org.springframework.lang.Nullable;
57+
import org.springframework.util.ReflectionUtils;
5658

5759
import java.util.*;
5860
import java.util.Map.Entry;
@@ -178,73 +180,115 @@ private ArangoCollection _collection(final String name, final ArangoPersistentEn
178180
@SuppressWarnings("deprecation")
179181
private static void ensureCollectionIndexes(final CollectionOperations collection,
180182
final ArangoPersistentEntity<?> persistentEntity) {
181-
persistentEntity.getPersistentIndexes().forEach(index -> ensurePersistentIndex(collection, index));
182-
persistentEntity.getPersistentIndexedProperties().forEach(p -> ensurePersistentIndex(collection, p));
183-
persistentEntity.getGeoIndexes().forEach(index -> ensureGeoIndex(collection, index));
184-
persistentEntity.getGeoIndexedProperties().forEach(p -> ensureGeoIndex(collection, p));
185-
persistentEntity.getFulltextIndexes().forEach(index -> ensureFulltextIndex(collection, index));
186-
persistentEntity.getFulltextIndexedProperties().forEach(p -> ensureFulltextIndex(collection, p));
187-
persistentEntity.getTtlIndex().ifPresent(index -> ensureTtlIndex(collection, index));
188-
persistentEntity.getTtlIndexedProperty().ifPresent(p -> ensureTtlIndex(collection, p));
189-
persistentEntity.getMDIndexes().forEach(index -> ensureMDIndex(collection, index));
190-
persistentEntity.getMDPrefixedIndexes().forEach(index -> ensureMDPrefixedIndex(collection, index));
191-
}
192-
193-
private static void ensurePersistentIndex(final CollectionOperations collection, final PersistentIndex annotation) {
194-
collection.ensurePersistentIndex(Arrays.asList(annotation.fields()),
195-
new PersistentIndexOptions()
183+
Collection<IndexEntity> existing = collection.getIndexes();
184+
persistentEntity.getPersistentIndexes().forEach(index -> ensurePersistentIndex(collection, index, existing));
185+
persistentEntity.getPersistentIndexedProperties().forEach(p -> ensurePersistentIndex(collection, p, existing));
186+
persistentEntity.getGeoIndexes().forEach(index -> ensureGeoIndex(collection, index, existing));
187+
persistentEntity.getGeoIndexedProperties().forEach(p -> ensureGeoIndex(collection, p, existing));
188+
persistentEntity.getFulltextIndexes().forEach(index -> ensureFulltextIndex(collection, index, existing));
189+
persistentEntity.getFulltextIndexedProperties().forEach(p -> ensureFulltextIndex(collection, p, existing));
190+
persistentEntity.getTtlIndex().ifPresent(index -> ensureTtlIndex(collection, index, existing));
191+
persistentEntity.getTtlIndexedProperty().ifPresent(p -> ensureTtlIndex(collection, p, existing));
192+
persistentEntity.getMDIndexes().forEach(index -> ensureMDIndex(collection, index, existing));
193+
persistentEntity.getMDPrefixedIndexes().forEach(index -> ensureMDPrefixedIndex(collection, index, existing));
194+
}
195+
196+
private static void ensurePersistentIndex(final CollectionOperations collection, final PersistentIndex annotation, Collection<IndexEntity> existing) {
197+
PersistentIndexOptions options = new PersistentIndexOptions()
196198
.unique(annotation.unique())
197199
.sparse(annotation.sparse())
198-
.deduplicate(annotation.deduplicate()));
200+
.deduplicate(annotation.deduplicate());
201+
Collection<String> fields = Arrays.asList(annotation.fields());
202+
if (existing.stream().noneMatch(index -> equalPersistentIndex(index, options, fields))) {
203+
collection.ensurePersistentIndex(fields, options);
204+
}
199205
}
200206

201207
private static void ensurePersistentIndex(final CollectionOperations collection,
202-
final ArangoPersistentProperty value) {
208+
final ArangoPersistentProperty value, Collection<IndexEntity> existing) {
203209
final PersistentIndexOptions options = new PersistentIndexOptions();
204210
value.getPersistentIndexed().ifPresent(i -> options
205211
.unique(i.unique())
206212
.sparse(i.sparse())
207213
.deduplicate(i.deduplicate()));
208-
collection.ensurePersistentIndex(Collections.singleton(value.getFieldName()), options);
214+
Collection<String> fields = Collections.singleton(value.getFieldName());
215+
if (existing.stream().noneMatch(index -> equalPersistentIndex(index, options, fields))) {
216+
collection.ensurePersistentIndex(fields, options);
217+
}
218+
}
219+
220+
private static boolean equalPersistentIndex(IndexEntity index, PersistentIndexOptions options, Collection<String> fields) {
221+
return isIndexWithTypeAndFields(index, IndexType.persistent, fields)
222+
&& isEqualOption(index.getUnique(), options.getUnique(), false)
223+
&& isEqualOption(index.getSparse(), options.getSparse(), false)
224+
&& isEqualOption(index.getDeduplicate(), options.getDeduplicate(), false);
209225
}
210226

211-
private static void ensureGeoIndex(final CollectionOperations collection, final GeoIndex annotation) {
212-
collection.ensureGeoIndex(Arrays.asList(annotation.fields()),
213-
new GeoIndexOptions().geoJson(annotation.geoJson()));
227+
private static void ensureGeoIndex(final CollectionOperations collection, final GeoIndex annotation, Collection<IndexEntity> existing) {
228+
GeoIndexOptions options = new GeoIndexOptions().geoJson(annotation.geoJson());
229+
Collection<String> fields = Arrays.asList(annotation.fields());
230+
if (existing.stream().noneMatch(index -> equalGeoIndex(index, options, fields))) {
231+
collection.ensureGeoIndex(fields, options);
232+
}
214233
}
215234

216-
private static void ensureGeoIndex(final CollectionOperations collection, final ArangoPersistentProperty value) {
235+
private static void ensureGeoIndex(final CollectionOperations collection, final ArangoPersistentProperty value, Collection<IndexEntity> existing) {
217236
final GeoIndexOptions options = new GeoIndexOptions();
218237
value.getGeoIndexed().ifPresent(i -> options.geoJson(i.geoJson()));
219-
collection.ensureGeoIndex(Collections.singleton(value.getFieldName()), options);
238+
Collection<String> fields = Collections.singleton(value.getFieldName());
239+
if (existing.stream().noneMatch(index -> equalGeoIndex(index, options, fields))) {
240+
collection.ensureGeoIndex(fields, options);
241+
}
242+
}
243+
244+
private static boolean equalGeoIndex(IndexEntity index, GeoIndexOptions options, Collection<String> fields) {
245+
return isIndexWithTypeAndFields(index, IndexType.geo, fields)
246+
&& isEqualOption(index.getGeoJson(), options.getGeoJson(), false);
220247
}
221248

222249
@SuppressWarnings("deprecation")
223-
private static void ensureFulltextIndex(final CollectionOperations collection, final FulltextIndex annotation) {
224-
collection.ensureFulltextIndex(Collections.singleton(annotation.field()),
225-
new FulltextIndexOptions().minLength(annotation.minLength() > -1 ? annotation.minLength() : null));
250+
private static void ensureFulltextIndex(final CollectionOperations collection, final FulltextIndex annotation, Collection<IndexEntity> existing) {
251+
Collection<String> fields = Collections.singleton(annotation.field());
252+
FulltextIndexOptions options = new FulltextIndexOptions().minLength(annotation.minLength() > -1 ? annotation.minLength() : null);
253+
if (existing.stream().noneMatch(index -> equalFulltextIndex(index, options, fields))) {
254+
collection.ensureFulltextIndex(fields, options);
255+
}
226256
}
227257

228258
@SuppressWarnings("deprecation")
229259
private static void ensureFulltextIndex(final CollectionOperations collection,
230-
final ArangoPersistentProperty value) {
260+
final ArangoPersistentProperty value, Collection<IndexEntity> existing) {
231261
final FulltextIndexOptions options = new FulltextIndexOptions();
232262
value.getFulltextIndexed().ifPresent(i -> options.minLength(i.minLength() > -1 ? i.minLength() : null));
233-
collection.ensureFulltextIndex(Collections.singleton(value.getFieldName()), options);
263+
Collection<String> fields = Collections.singleton(value.getFieldName());
264+
if (existing.stream().noneMatch(index -> equalFulltextIndex(index, options, fields))) {
265+
collection.ensureFulltextIndex(fields, options);
266+
}
267+
}
268+
269+
private static boolean equalFulltextIndex(IndexEntity index, FulltextIndexOptions options, Collection<String> fields) {
270+
return isIndexWithTypeAndFields(index, IndexType.fulltext, fields)
271+
&& isEqualOption(index.getMinLength(), options.getMinLength(), 0);
234272
}
235273

236-
private static void ensureTtlIndex(final CollectionOperations collection, final TtlIndex annotation) {
237-
collection.ensureTtlIndex(Collections.singleton(annotation.field()),
238-
new TtlIndexOptions().expireAfter(annotation.expireAfter()));
274+
private static void ensureTtlIndex(final CollectionOperations collection, final TtlIndex annotation, Collection<IndexEntity> existing) {
275+
TtlIndexOptions options = new TtlIndexOptions().expireAfter(annotation.expireAfter());
276+
Collection<String> fields = Collections.singleton(annotation.field());
277+
if (existing.stream().noneMatch(index -> equalTtlIndex(index, options, fields))) {
278+
collection.ensureTtlIndex(fields, options);
279+
}
239280
}
240281

241-
private static void ensureTtlIndex(final CollectionOperations collection, final ArangoPersistentProperty value) {
282+
private static void ensureTtlIndex(final CollectionOperations collection, final ArangoPersistentProperty value, Collection<IndexEntity> existing) {
242283
final TtlIndexOptions options = new TtlIndexOptions();
243284
value.getTtlIndexed().ifPresent(i -> options.expireAfter(i.expireAfter()));
244-
collection.ensureTtlIndex(Collections.singleton(value.getFieldName()), options);
245-
}
285+
Collection<String> fields = Collections.singleton(value.getFieldName());
286+
if (existing.stream().noneMatch(index -> equalTtlIndex(index, options, fields))) {
287+
collection.ensureTtlIndex(fields, options);
288+
}
289+
}
246290

247-
private static void ensureMDIndex(final CollectionOperations collection, final MDIndex annotation) {
291+
private static void ensureMDIndex(final CollectionOperations collection, final MDIndex annotation, Collection<IndexEntity> existing) {
248292
collection.ensureMDIndex(Arrays.asList(annotation.fields()),
249293
new MDIndexOptions()
250294
.unique(annotation.unique())
@@ -253,7 +297,7 @@ private static void ensureMDIndex(final CollectionOperations collection, final M
253297
);
254298
}
255299

256-
private static void ensureMDPrefixedIndex(final CollectionOperations collection, final MDPrefixedIndex annotation) {
300+
private static void ensureMDPrefixedIndex(final CollectionOperations collection, final MDPrefixedIndex annotation, Collection<IndexEntity> existing) {
257301
collection.ensureMDPrefixedIndex(Arrays.asList(annotation.fields()),
258302
new MDPrefixedIndexOptions()
259303
.prefixFields(Arrays.asList(annotation.prefixFields()))
@@ -263,6 +307,28 @@ private static void ensureMDPrefixedIndex(final CollectionOperations collection,
263307
);
264308
}
265309

310+
private static boolean equalTtlIndex(IndexEntity index, TtlIndexOptions options, Collection<String> fields) {
311+
return isIndexWithTypeAndFields(index, IndexType.ttl, fields)
312+
&& isEqualOption(index.getExpireAfter(), getProtected(options, "getExpireAfter"), 0);
313+
}
314+
315+
private static boolean isIndexWithTypeAndFields(IndexEntity index, IndexType type, Collection<String> fields) {
316+
return index.getType() == type && index.getFields().size() == fields.size() && index.getFields().containsAll(fields);
317+
}
318+
319+
private static <T> boolean isEqualOption(T value, @Nullable T optionalValue, T defaultValue) {
320+
return value.equals(optionalValue == null ? defaultValue : optionalValue);
321+
}
322+
323+
@SuppressWarnings("unchecked")
324+
@Deprecated
325+
// can be removed for driver 7 as all option getters are visible
326+
private static <T> T getProtected(Object options, String getterName) {
327+
Method getter = ReflectionUtils.findMethod(options.getClass(), getterName);
328+
ReflectionUtils.makeAccessible(getter);
329+
return (T) ReflectionUtils.invokeMethod(getter, options);
330+
}
331+
266332
private Optional<String> determineCollectionFromId(final Object id) {
267333
return id != null ? Optional.ofNullable(MetadataUtils.determineCollectionFromId(converter.convertId(id)))
268334
: Optional.empty();

0 commit comments

Comments
 (0)