В этом посте рассказывается о некоторых новых функциях, добавленных в Neo4jD в последние дни.
Persist Статический типизированный объект
В предыдущем посте я объяснил, как создать Node и Relationship с помощью Neo4jD. Как вы могли заметить, свойства Node являются динамическими, например, чтобы задать FirstName, мы говорим «node.SetProperty (« FirstName »,« Sony »)». Как и я, большинству из нас не нравятся динамические свойства, поэтому мы создаем статические объекты. Этот пост посвящен тому, как сохранить статические объекты в Neo4j.
Примечание: я не против Dynamics, это просто личное предпочтение не строить вокруг Dynamics.
Давайте поговорим с некоторыми примерами.
public class Person
{
public Person()
{
this.Address = new Address();
}
[EntityId]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class Address
{
[EntityId]
public int AddressId { get; set; }
public string Address1 { get; set; }
public string City { get; set; }
}
Итак, у меня есть два класса для хранения моих данных. Давайте посмотрим, как сохранить объект с помощью Neo4jD. Ядро Neo4jD основано на Node и Relationship с динамическими свойствами. Вдобавок к ядру я добавил маппер для сопоставления статических типизированных сущностей с узлами или связями. Я не собираюсь углубляться в понимание картографа, просто расскажу, например, если вам нужно больше понимания, лучше изучите Neo4jD в github .
Как сохранить объект
[TestCase]
public Person SaveTest()
{
Person person = new Person { FirstName = "Sony", LastName= "Arouje"};
NodeMapper mapper = new NodeMapper();
person=mapper.Save<Person>(person);
Console.WriteLine("Generated Id: " + person.Id.ToString());
Assert.AreNotEqual(0, person.Id);
return person;
}
За кулисами NodeMapper использует отражение, чтобы получить данные из объекта Person и создать объект Node. Посмотрим, как я это делаю.
public T Save<T>(T entity) where T:class
{
Node node = this.CreateNode<T>(entity);
node.Create();
return MapperHelper.SetIdentity<T>(entity, node.Id);
}
private Node CreateNode<T>(T entity) where T:class
{
Node node = new Node();
node.AddProperty("clazz", typeof(T).ToString());
typeof(T).GetProperties().Where(pr => pr.CanRead && MapperHelper.IsAnId(pr) == false)
.ToList().ForEach(property =>
{
if(MapperHelper.IsPrimitive(property.PropertyType))
node.AddProperty(property.Name, property.GetValue(entity, null).ToString());
});
return node;
}
Функция CreateNode выполняет сопоставление. Итерирует через свойство и вызывает node.AddProperty (property.Name, property.GetValue ()), это то же самое, что и node.AddProperty («FirstName», «Sony»).
Вы могли заметить, что поле Id в классе имеет атрибут EntityId. Это обязательный атрибут для получения или установки идентификатора узла в поле идентификатора объекта.
Получить экземпляр от Neo4J
[TestCase]
public void GetPersonById()
{
NodeMapper mapper = new NodeMapper();
Person person = mapper.Get<Person>(7);
Console.WriteLine("Generated Id: " + person.Id.ToString());
Assert.AreNotEqual(0, person.Id);
Assert.AreEqual(“Sony”, person.FirstName);
}
Чтобы получить человека, которого я назвал mapper.Get с уникальным идентификатором человека, и картограф вернет действительного человека, если он существует в БД. NodeMapper использует нижеприведенную функцию для генерации объекта.
public T Get<T>(int id) where T:class
{
Node node = Node.Get(id);
T entity = (T)Activator.CreateInstance(typeof(T));
if (node.GetProperty("clazz")!=typeof(T).ToString())
throw new InvalidCastException(string.Format("Retrieved object with ID '{0}' is
an instance of '{1}' and unable to cast it to '{2}'", id.ToString(),
node.GetProperty("clazz"), typeof(T).ToString()));
typeof(T).GetProperties().Where(pr => pr.CanRead && MapperHelper.IsAnId(pr) == false)
.ToList().ForEach(property =>
{
property.SetValue(entity, MapperHelper.CastPropertyValue(property,
node.GetProperty(property.Name)), null);
});
entity = MapperHelper.SetIdentity<T>(entity, id);
return entity;
}
Создать отношения
Вы можете видеть, что Person имеет экземпляр Address, в Graph Person связан с Address. Давайте посмотрим, как мы можем создать это
[TestCase]
public void CanCreateRelationships()
{
Person person = new Person { FirsName = "Sony", LastName = "Arouje" };
person.Address.Address1 = "EcoSpace";
person.Address.City = "Bangalore";
NodeMapper mapper = new NodeMapper();
mapper.CreateRelationshipTo<Person, Address>(person,person.Address);
Console.WriteLine(person.Id.ToString());
Assert.AreEqual(1, person.Id);
}
Функция CreateRelationShipTo будет сохранять как Персона, так и Адрес, если она не сохранена, иначе она создаст связь. В Neo4j отношения будут персона-> адрес.
Получить человека с отношениями
[TestCase]
public void CanGetRelatedNodes()
{
NodeMapper mapper = new NodeMapper();
Person person = mapper.Get<Person>(12);
IList<Address> address = mapper.GetRelatedEntities<Person, Address>(person, typeof(Address));
Assert.AreEqual(1, address.Count);
Assert.AreEqual("EcoSpace", address[0].Address1);
}
Я знаю, что сохраняющиеся и извлекающие отношения немного запутаны, я буду работать над этим, чтобы сделать его более ясным и тихим.
Это все о сохранении статических объектов в Neo4j.
В следующем посте я расскажу о создании индекса, обхода с использованием Germlin и REST.