@CompositeIndex not working

Hi,
I'm using @CompositeIndex for creating index on multiple attributes on a node.
Please find the code and error below. Any help will be highly appreciated.

Code:

package com.test.neo4j.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import org.neo4j.ogm.annotation.CompositeIndex;
import org.neo4j.ogm.annotation.GeneratedValue;
//import org.neo4j.ogm.annotation.CompositeIndexes;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.Index;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Property;
import org.springframework.beans.factory.annotation.Value;

@Data
@NoArgsConstructor
@AllArgsConstructor
@NodeEntity
@CompositeIndex(value= {"indexValue1","indexValue2"}, unique=true)
public class CompIndTestNode {
    String indexValue1;
    String indexValue2;
    String value3;
}

Error:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'neo4jAuditionBeanFactoryPostProcessor': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.neo4j.ogm.session.SessionFactory]: Factory method 'sessionFactory' threw exception; nested exception is org.neo4j.ogm.exception.core.MetadataException: Incorrect CompositeIndex definition on com.test.neo4j.domain.CompIndTestNode. Property indexValue1 does not exists.
               at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:732)
               at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:197)
               at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1267)
               at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1124)
               at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535)
               at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
               at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
               at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
               at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
               at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204)
               at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:236)
               at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:710)
               at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:535)
               at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
               at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780)
               at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412)
               at org.springframework.boot.SpringApplication.run(SpringApplication.java:333)
               at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277)
               at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265)
               at com.test.neo4j.App.main(App.java:11)
               at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
               at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
               at java.lang.reflect.Method.invoke(Method.java:498)
               at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.neo4j.ogm.session.SessionFactory]: Factory method 'sessionFactory' threw exception; nested exception is org.neo4j.ogm.exception.core.MetadataException: Incorrect CompositeIndex definition on com.test.neo4j.domain.CompIndTestNode. Property indexValue1 does not exists.
               at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590)
               at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1247)
               at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1096)
               at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535)
               at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
               at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
               at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
               at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
               at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
               at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
               at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1135)
               at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062)
               at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:818)
               at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:724)
               ... 24 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.neo4j.ogm.session.SessionFactory]: Factory method 'sessionFactory' threw exception; nested exception is org.neo4j.ogm.exception.core.MetadataException: Incorrect CompositeIndex definition on com.test.neo4j.domain.CompIndTestNode. Property indexValue1 does not exists.
               at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
               at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:582)
               ... 37 common frames omitted
Caused by: org.neo4j.ogm.exception.core.MetadataException: Incorrect CompositeIndex definition on com.test.neo4j.domain.CompIndTestNode. Property indexValue1 does not exists.
               at org.neo4j.ogm.metadata.ClassInfo.compositeIndexes(ClassInfo.java:897)
               at org.neo4j.ogm.metadata.ClassInfo.getCompositeIndexes(ClassInfo.java:867)
               at org.neo4j.ogm.autoindex.AutoIndexManager.initialiseIndexMetadata(AutoIndexManager.java:75)
               at org.neo4j.ogm.autoindex.AutoIndexManager.<init>(AutoIndexManager.java:57)
               at org.neo4j.ogm.session.SessionFactory.<init>(SessionFactory.java:85)
               at org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration.sessionFactory(Neo4jDataAutoConfiguration.java:75)
               at org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration$$EnhancerBySpringCGLIB$$4490ada6.CGLIB$sessionFactory$2(<generated>)
               at org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration$$EnhancerBySpringCGLIB$$4490ada6$$FastClassBySpringCGLIB$$c85034c1.invoke(<generated>)
               at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
               at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)
               at org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration$$EnhancerBySpringCGLIB$$4490ada6.sessionFactory(<generated>)
               at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
               at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
               at java.lang.reflect.Method.invoke(Method.java:498)
               at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
               ... 38 common frames omitted


Process finished with exit code 0

Hi Tom,
Thanks for your response!
We can put @Index inside the class but as per my understanding @CompositeIndex will be on top of class mentioning all the attributes for which Index needs to be created, as I’ve mentioned in the sample.

Please correct me if I’m wrong.

Also, it will be great if you can point to some working example.

Thanks,
Sukaant

Hello Sukaant,

You are right (and I deleted my reply as to not create confusion). The only example I could find is at https://github.com/neo4j/neo4j-ogm/blob/master/test/src/test/java/org/neo4j/ogm/domain/autoindex/CompositeIndexEntity.java ... but that looks the same as yours. I'll check further and get back to you.

Regards,
Tom

Hi Sukaant,

Can you confirm that all nodes with the label CompIndTestNode have both the properties indexValue1 and indexValue2? I know this does fail for me when at least one node does not have both properties. You can check using a simple query like:

match (c:CompIndTestNode)
where not exists(c.indexValue1) OR not exists(c.indexValue2)
return count(c);

If this returns more than 0, then this is the problem.

Thanks, Dave

Hi Dave,
Thanks for your response!

I’m trying to create this node for the first time, It is not there in the database. I’m getting this error when I’m starting the application.
This error comes when I put @CompositeIndex.
I never got the luck to call the service with @CompositeIndex.

Also, as you mentioned I’m taking care of indexValue1 and indexValue2 as the mandatory attributes for CompIndTestNode.

Thanks,
Sukaant

Ok thanks for clarifying. We are looking into this and will have some progress to report later in the week.

Thanks, Dave

Could you give a better outline of your entity? Where does the id live?

I just leave my short example here (also with Lombok)

public class IndexExample {

  public static void main(String[] args) {
	SessionFactory sessionFactory = new SessionFactory(new Configuration.Builder()
		.uri("bolt://localhost")
		.credentials("neo4j", "secret")
		.autoIndex(AutoIndexMode.ASSERT.getName())
		.build(), "org.neo4j.ogmindex.index");

	Session session = sessionFactory.openSession();
	session.deleteAll(IndexEntity.class);

	IndexEntity entity = new IndexEntity(null, "a", "b"); // setting id null to force creation
	session.save(entity);

	System.out.println(entity.toString());

	sessionFactory.close();
  }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@NodeEntity
@CompositeIndex(value = {"a", "b"}, unique = true)
class IndexEntity {

  private Long id;

  private String a;
  private String b;

}

When I run this I can see the index creation in the log.

you can try set the value with lowercase,

@CompositeIndex(value= {"indexvalue1","indexvalue2"}, unique=true),

in neo4j-ogm(3.1.2) 's source
code, propertyFields's key was stored as lowercase.

private synchronized void initPropertyFields() {
        if (fieldInfos != null) {
            return;
        }

        Collection<FieldInfo> fields = fieldsInfo().fields();

        FieldInfo identityField = identityFieldOrNull();
        Set<FieldInfo> fieldInfos = new HashSet<>(fields.size());
        Map<String, FieldInfo> propertyFields = new HashMap<>(fields.size());

        for (FieldInfo fieldInfo : fields) {
            if (fieldInfo != identityField && !fieldInfo.isLabelField()
                && !fieldInfo.hasAnnotation(StartNode.class)
                && !fieldInfo.hasAnnotation(EndNode.class)) {

                // If a field is not marked explicitly as a property but is persistable as such, add it.
                if (!fieldInfo.getAnnotations().has(Property.class)) {
                    if (fieldInfo.persistableAsProperty()) {
                        fieldInfos.add(fieldInfo);
                        propertyFields.put(fieldInfo.property().toLowerCase(), fieldInfo);
                    }
                }
                // If it is marked as a property, than it should be persistable as such
                else if (fieldInfo.persistableAsProperty()) {
                    fieldInfos.add(fieldInfo);
                    propertyFields.put(fieldInfo.property().toLowerCase(), fieldInfo);
                }
                // Otherwise throw a fitting exception
                else {
                    throw new InvalidPropertyFieldException(fieldInfo);
                }
            }
        }

        this.fieldInfos = fieldInfos;
        this.propertyFields = propertyFields;
    }

The usage of toLowerCase in the internal API was fixed in 3.1.7/