Skip to content

Commit

Permalink
feat(update): update multiple document references
Browse files Browse the repository at this point in the history
It's now possible to update multiple document references when using updateNeo(). (Tests succeed).
  • Loading branch information
SvenWesterlaken committed Dec 5, 2018
1 parent 822a92d commit 975a898
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 30 deletions.
77 changes: 50 additions & 27 deletions lib/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = {

const updates = _.merge(_.pick(doc, _.keys(criteria)), criteria);

let match_clause = `MERGE (doc:${helper.getLabel(doc)} {m_id: '${doc._id}'})`;
let match_clause = `MATCH (doc:${helper.getLabel(doc)} {m_id: '${doc._id}'})`;
let set_clause = '';

const neo_updates = node.convertToNeoUpdates(schema, updates, doc);
Expand All @@ -19,22 +19,43 @@ module.exports = {
match_clause += subdocs_query.match_clause;
set_clause += subdocs_query.set_clause;

set_clause = set_clause === '' ? ' ' : ' SET' + set_clause.substring(1);
set_clause = set_clause === '' ? '' : ' SET' + set_clause.substring(1);

const doc_query = match_clause + set_clause;

const relationships_query = this.writeRelationshipsToCypher(neo_updates.rels);
const { relationships_query, relationships_del_query } = this.writeRelationshipsToCypher(neo_updates.rels, doc);

const neo_query = doc_query + relationships_query;

console.log(neo_query);
// console.log(neo_query);

const session = driver.session();

return Promise.all([doc.update(criteria, options, cb), session.run(neo_query)]).then((results) => {
session.close();
return results;
});
if (relationships_del_query !== '') {

return session.run(relationships_del_query).then((del_result) => {
return Promise.all([
doc.update(criteria, options, cb),
session.run(neo_query),
del_result
]);
}).then((results) => {
session.close();
return results;
});

} else {
return Promise.all([
doc.update(criteria, options, cb),
session.run(neo_query)
]).then((results) => {
session.close();
return results;
});
}



},

writePropertiesToCypher(properties, doc_identifier, is_subdoc) {
Expand All @@ -55,7 +76,7 @@ module.exports = {
return neo_query;
},

writeSubDocumentsToCypher(subdocs, doc) {
writeSubDocumentsToCypher(subdocs) {
let match_clause = "";
let set_clause = "";

Expand All @@ -70,34 +91,36 @@ module.exports = {
return { match_clause, set_clause };
},

writeRelationshipsToCypher(relationships) {
let neo_query = '';
let relationLabels = [];
writeRelationshipsToCypher(relationships, doc) {
let relationships_query = '';
let relationships_del_query = '';

if(!_.isEmpty(relationships)) {
let relationLabels = [];

_.forEach(relationships, (rel, index) => {
const properties = rel.rel_props ? ` ${helper.toPlainString(rel.rel_props)}` : '';
relationLabels.push(rel.rel_name);
let match_clause = [];
let create_clause = [];

neo_query += `WITH doc `;
neo_query += `MATCH (rel_doc:${rel.rel_label}) WHERE rel_doc.m_id = '${rel.m_id}' `;
neo_query += `CREATE (doc)-[:${rel.rel_name}${properties}]->(rel_doc) `;
_.forEach(relationships, (rel, index) => {
const identifier = helper.romanize(index+1);
const properties = rel.rel_props ? ` ${helper.toPlainString(rel.rel_props)}` : '';
relationLabels.push(rel.rel_name);

});
match_clause.push(`(${identifier}:${rel.rel_label} {m_id: '${rel.m_id}'})`);
create_clause.push(`(doc)-[:${rel.rel_name}${properties}]->(${identifier})`);

console.log(relationLabels);
});

relationships_query = `, ${_.join(match_clause, ', ')} CREATE ${_.join(create_clause, ', ')} `;

if(!_.isEmpty(relationships)) {
relationLabels = JSON.stringify(_.uniq(relationLabels));

let delete_clause = `WITH doc `;
delete_clause += `MATCH (doc)-[r]->() `;
delete_clause += `WHERE type(r) IN ${relationLabels} `;
delete_clause += `DELETE r `;
relationships_del_query = `MATCH (doc)-[r]->(n) WHERE type(r) IN ${relationLabels} DELETE r`;


neo_query = delete_clause + neo_query;
}

return neo_query;
return { relationships_query, relationships_del_query };
}

};
57 changes: 54 additions & 3 deletions test/functions/update_test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { Person, Class, driver, chai, expect, int } = require('../helper');

const getStats = function(results) {
return results[1].summary.counters._stats
const getStats = function(results, has_delete = false) {
return results[has_delete ? 2 : 1].summary.counters._stats
}

describe('Mongo4J Updating', () => {
Expand Down Expand Up @@ -210,10 +210,11 @@ describe('Mongo4J Updating', () => {
return result.updateNeo(chemistry_update);

}).then((results) => {
const neo_del_stats = getStats(results, true);
const neo_stats = getStats(results);

expect(neo_stats.relationshipsCreated).to.equal(1);
expect(neo_stats.relationshipsDeleted).to.equal(1);
expect(neo_del_stats.relationshipsDeleted).to.equal(1);
expect(results[0].ok).to.equal(1);

return session.run('MATCH (n:Class)-[p]-(a:Person) RETURN n,p,a;');
Expand All @@ -236,4 +237,54 @@ describe('Mongo4J Updating', () => {

});

it('Update an array of document references', (done) => {
const daniel = new Person({firstName: "Daniel", lastName: "Durval"});
const henry = new Person({firstName: "Henry", lastName: "McCoverty"});
const jason = new Person({firstName: "Jason", lastName: "Campbell"});

Person.insertMany([daniel, neil, henry, jason]).then((result) => {

expect(result).to.not.be.null;
expect(result).to.have.a.lengthOf(4);
expect(result).to.contain.something.with.a.property('firstName', neil.firstName);
expect(result).to.contain.something.with.a.property('lastName', daniel.lastName);
expect(result).to.contain.something.with.a.property('firstName', henry.firstName);
expect(result).to.contain.something.with.a.property('lastName', jason.lastName);

const chemistry = new Class({
title: 'Chemistry',
students: [daniel._id, neil._id]
});

return chemistry.save();

}).then((result) => {

expect(result).to.not.be.null;
expect(result).to.have.a.property('_id');
expect(result).to.have.a.property('isNew', false);
expect(result.students).to.be.an('Array');
expect(result.students).to.have.a.lengthOf(2);


const chemistry_update = {
students: [henry._id, jason._id]
};

return result.updateNeo(chemistry_update);

}).then((results) => {
const neo_del_stats = getStats(results, true);
const neo_stats = getStats(results);

expect(neo_stats.relationshipsCreated).to.equal(2);
expect(neo_del_stats.relationshipsDeleted).to.equal(2);
expect(results[0].ok).to.equal(1);

done();
});


});

});

0 comments on commit 975a898

Please sign in to comment.