I have an entity Place:
#NodeEntity
#TypeAlias(value="Place")
public class Place implements Serializable{
private static final long serialVersionUID = 1L;
#GraphId
private Long nodeId;
#JsonProperty("id")
#Indexed(unique=true)
private String id;
//...
}
And I try to get a node based on its id attribute this way:
String pfc = "1234";
(Node)template.getIndex(Place.class, "id").get("id", pfc).getSingle()
But I'm having this exception :
java.lang.IllegalStateException: Index name for class java.lang.String id rel: false idx: true must differ from the default name: Place
Must I necessairly add a name to the index?
If yes, how should I do for the existent data?
Which version are you using? In SDN 3.x for Neo4j 2.x the indexes and constraints are used automatically.
I would use a PlaceRepository with a findById() method.
Or in general cypher queries that access place like this:
MATCH (p:Place {id:{id}})-->(x)
RETURN x
You can access them manually with template.merge() or template.findByLabelAndProperty() which I would only recommend when you know what you're doing.
Related
I have a neo4j database, and one of the nodes in the database has the following:
public class Location
{
.
.
.
#Property(name = "zone_quantities")
private List<ZoneQuantity> zoneQuantityList;
}
When I try to use ogm to map the node into the object, I get the following error:
Caused by: org.neo4j.ogm.exception.core.InvalidPropertyFieldException: 'com.livspace.atp.domain.InvSku#zoneQuantityList' is not persistable as property but has not been marked as transient.
Neo4j version - 3.1.6
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class ZoneQuantity {
private String zone;
private Integer quantity;
}
Neo4j-OGM does not know what to do with the custom type property ZoneQuantity.
It is either a relationship and has to get described as such e.g.
#Relationship("HAS_ZONE")
private List<ZoneQuantity> zoneQuantityList;
or you need to provide an AttributeConverter for your custom type (collection) that converts it into a database compatible type. For example something like this converter https://github.com/neo4j/neo4j-ogm/blob/master/core/src/main/java/org/neo4j/ogm/typeconversion/NumberCollectionStringConverter.java#L37
After upgrading the spring boot to 2.2.4 (from 2.1.x), org.springframework.cloud:spring-cloud-dependencies to Hoxton.RELEASE and org.springframework.cloud:spring-cloud-stream-dependencies to Horsham.RELEASE.
Getting the following exception when trying to create index document.
Caused by: org.springframework.data.mapping.MappingException: Attempt to add id property private java.util.Map .CatalogIndex.document but already have property private java.lang.String .CatalogIndex.id registered as id. Check your mapping configuration!
Please find the entity class hierarchy. I have removed all the getter and setter for simplicity.
package mypackage.entity;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Parent;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class CatalogIndex {
private static final long serialVersionUID = 1L;
#Id
private String id;
#Parent(type = "Initiative")
private String initiativeId;
private List<Map<String, Object>> typeHierarchy;
private Map<String, Object> document;
private List<Map<String, Object>> filters;
}
package mypackage.entity;
import org.springframework.data.elasticsearch.annotations.Document;
#Document(indexName = "cataloginitiative")
public class CatalogInitiativeIndex extends CatalogIndex { }
Spring Data Elasticsearch, when inspecting the Entity class, tries to figure out which property of the class is to be used as the Id property. A property qualifies for this if one of the following is true:
the property is annotated with #Id
the property is named id
the property is named document
So in your case you have the property id which has a matching name and the annotation, and the property document with a matching name.
You have to rename your property document to somthing different.
I am using the 1.5.1 version of the Cassandra adapter for Java, and I am attempting to insert a record to a table having a Map column that uses a UDT as the column value (key is just a varchar). I created the table using cqlsh and am able to insert to it in CQL just fine. When i try to use a CassandraTemplate...insert(), though, all I get is:
UserTypeResolver must not be null
My UDT class is defined as:
#UserDefinedType("iss_type")
public class IssueType {
#CassandraType(type = DataType.Name.VARCHAR)
private String issue_code;
#CassandraType(type = DataType.Name.VARCHAR)
private String issue_name;
#CassandraType(type = DataType.Name.TIMESTAMP)
private Date issue_start;
#CassandraType(type = DataType.Name.TIMESTAMP)
private Date issue_end;
And my table is defined as
#Table
public class IssueMap {
#PrimaryKeyColumn(
type = PrimaryKeyType.PARTITIONED)
private UUID map_id;
#Column
private Map<String, IssueType> issue_map;
In my config, i have:
#Bean
public CassandraMappingContext cassandraMapping()
throws ClassNotFoundException {
BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();
mappingContext.setUserTypeResolver(new SimpleUserTypeResolver(cluster().getObject(),"campaign_management"));
return mappingContext;
}
Is there something I am missing here? Or is it just not possible to define columns this way? I realize I could just use a query builder to create the CQL and do the insert, but I was hoping to be able to make full use of the Cassandra template features.
Let us assume following:
1). We have two entities:
#NodeEntity
public class A {
#GraphId
private Long id;
...
}
#NodeEntity
public class B {
#GraphId
private Long id;
...
}
2). We have two appropriate repositories:
public interface ARepository extends GraphRepository<A> {
...
}
public interface BRepository extends GraphRepository<B> {
...
}
3). And we have following nodes in database:
A with id=1
B with id=2
Case a: Now assume we need to check whether A with id=2 is exists:
ARepository.exists(2)
I expect that it will return false, since A with id=2 isn't exists. But it returns true, since it tries to find among all ids, not only among A nodes.
Case b: Or maybe we need to find B with id=1:
BRepository.findOne(1);
I expect that it returns null or throws appropriate exception, informing that B with id=1 isn't exists. But it throws unexpected for me PersistentEntityConversionException.
Hence questions:
How can we use aforementioned operations with expected behavior?
May be there is workaround?
I'm converting a working system that uses #Fetch to a lazy load strategy. However, when I retrieve the object with a container, the container only has one entry and neo4jTemplate.fetch(obj.getContainer()) does not retrieve the other entries.
Here are the pertinent snippets
#NodeEntity
public class SourcePage {
#GraphId
private Long id;
#RelatedTo(type = "GROUP_MEMBER")
private Group group;
Group Class:
#NodeEntity
public class Group {
#GraphId
private Long id;
#RelatedTo(type = "GROUP_MEMBER", direction = Direction.INCOMING)
private Set<SourcePage> sourcePages = new HashSet<>();
Test Code:
Group group1 = groupRepository.findByName("Test Group");
neo4jTemplate.fetch(group1.getSourcePages());
assertThat(group1.getSourcePages().size(), is(254));
The Result:
java.lang.AssertionError:
Expected: is <254>
but: was <1>
If I do nothing but add #Fetch to private Group group, then it all works as expected.
Also, I looked at the database server with only this test example and ran this query:
MATCH (a)-[:`GROUP_MEMBER`]->(b) RETURN count(b)
It returned 254 as expected. I have also tried direction.BOTH on each side of the relationship - same results.
I found the problem. It's esoteric and plausible enough that it might help someone else seeing the same symptom.
First, I didn't show that I had my own hashCode() for SourcePage. It hashed a field defined as:
#NotEmpty
#Indexed
private String url;
Without #Fetch the 'url' is not retrieved automatically, so all the SourcePages in the container have the same hash code. This resulted in 100% collisions and only one entry added to the set.
If I removed the hashCode() then the default hash worked and all the objects were added to the set.
After several hours of debugging, I posted my question. Of course right after that I stumbled on the solution.
Moral of the story: don't provide a hash function on member data without the ID.