0
votes

I am trying to make an application with spring-boot as backend and Angular as a frontend, and as a Neo4j Database that is a Graph-oriented NoSQL database. My problem is that I do not know how to use complex data in the NodeEntity, I mean. The application that I am programming will be based on a microservices architecture where the app made in Angular (frontend) will insert and consume the data by a Rest API of the backend made with spring-boot which will store the data in a server that is running an instance from the Neo4j database. Here is an example of what I am doing. This is the application.properties file

spring.data.neo4j.uri=bolt://localhost spring.data.neo4j.username=neo4j spring.data.neo4j.password=secret

This is my example class of the domain model:

@NodeEntity
public class Contact {
    @Id
    Long id;
    String name;
    String address;
    String city;
    String phone;
    String email;

    public Contact(String name, String address, String city, String phone, String email) {
        this.name = name;
        this.address = address;
        this.city = city;
        this.phone = phone;
        this.email = email;
    }
//get and set
    }

As you can see is a simple class with different attributes, but these attributes by their nature can be more complex data such as address that can be a NodeEntity by itself that consists of the attributes, city, street, country, #, ...

My repository would be something simple like this:

public interface ContactRepository extends Neo4jRepository<Contact,Long>{
    Collection<Contact> findByName(String name);
    @Override
    void delete(Contact deleted);
}

The ContactService class would be in charge of handling the ContactRepository

@Service
public class ContactService {
    @Autowired
    private final ContactRepository contactRepository;

    public ContactService(ContactRepository contactRepository) {
        this.contactRepository = contactRepository;
    }

    @Transactional(readOnly = true)
    public Iterable<Contact> contact() {
        return contactRepository.findAll();
    }

    @Transactional(readOnly = true)
    public Contact show(Long id) {
        return contactRepository.findById(id).get();
    }

    public Contact save(Contact contact) {
        contactRepository.save(contact);

        return contact;
    }

    public Contact update(Long id, Contact contact) {
        Contact c = contactRepository.findById(id).get();
        if (contact.getName() != null)
            c.setName(contact.getName());
        if (contact.getAddress() != null)
            c.setAddress(contact.getAddress());
        if (contact.getPhone() != null)
            c.setPhone(contact.getPhone());
        if (contact.getEmail() != null)
            c.setEmail(contact.getEmail());
        contactRepository.save(c);
        return contact;
    }
    public String delete(Long id) {
        Contact contact = contactRepository.findById(id).get() ;
        contactRepository.delete(contact);

        return "";
    }
}

Finally, the controller in charge of the Rest API

@RestController
public class ContactController {
    @Autowired
    private ContactService contactService;

    @RequestMapping(method = RequestMethod.GET,value = "/contacts")
    public Iterable<Contact> contact(){
        return contactService.contact();
    }

    @RequestMapping(method = RequestMethod.POST,value = "/contacts")
    public Contact save(@RequestBody Contact contact){
        return contactService.save(contact);
    }
    @RequestMapping(method = RequestMethod.GET,value = "/contacts/{id}")
    public Contact show(@PathVariable Long id){
        return contactService.show(id);
    }
    @RequestMapping(method = RequestMethod.PUT,value = "/contacts/{id}")
    public Contact update(@PathVariable Long id,@RequestBody Contact contact){
       return contactService.update(id,contact);
    }
    @RequestMapping(method = RequestMethod.DELETE,value = "/contacts/{id}")
    public String delete(@PathVariable Long id){
        contactService.delete(id);
        return "";
    }
}

To test how the API works, the following command is used

curl -i -H "Accept: application/json" localhost:8080/contacts

and as a result

HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 05 Jul 2018 12:14:39 GMT []

To insert a new contact in the Database

curl -i -X POST -H "Content-Type: application/json" -d '{"name":"John Doe","address":"Jl. Cipaganti No.112","city":"Bandung","phone":"0811223112233","email":"[email protected]"}' localhost:8080/contacts

which returns as a result

HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Tue, 06 Jul 2018 02:59:00 GMT {"id":"5a7919f4b9d4f13c2cb6f539","name":"John Doe","address":"Jl. Cipaganti No.112","city":"Bandung","phone":"0811223112233","email":"[email protected]"}

The question arises when I try to change the address attribute for a NodeEntity Class, since I have seen many tutorials, but only how to consume the Rest API does not give how to insert the data. How could I add to the Contact Class an address attribute that is a class that represents a Node (NodeEntity) in the Database? How can I execute the curl command to prove that the api works correctly because now the address attribute would be a class with several attributes such as city, street, country, #, ...?

I hope you can help me and thank you for your time.

1

1 Answers

1
votes
@NodeEntity
public class Contact {
@Id
Long id;
String name;
@Relationship(type = HAS_ADDRESS)
Address address;
}
just create a relationship between 2 nodes and save as an embeded node.

You cal create address node similar to above node as

@NodeEntity
public class Address{ 
 // properties and getter setters.
}