-
Notifications
You must be signed in to change notification settings - Fork 41
Using Neo4j
Gilbert edited this page Apr 15, 2016
·
3 revisions
(code dump)
lib/db.js
- This gives us a promisified way to make queries to the database.
var Bluebird = require('bluebird')
var db = require('seraph')({
server: 'http://localhost:7474',
user: 'neo4j', // <-- Change these according to your setup
pass: 'dev' // <--
})
// Promisify seraph API
Bluebird.promisifyAll(db, { suffix: '_p' })
Bluebird.promisifyAll(db.node, { suffix: '_p' })
Bluebird.promisifyAll(db.rel, { suffix: '_p' })
Bluebird.promisifyAll(db.index, { suffix: '_p' })
Bluebird.promisifyAll(db.constraints, { suffix: '_p' })
Bluebird.promisifyAll(db.constraints.uniqueness, { suffix: '_p' })
module.exports = db
db.deleteEverything = function () {
if (process.env.NODE_ENV === 'production') return;
var query = `
MATCH (n)
DETACH DELETE n
RETURN 0
`
return db.queryRaw_p(query)
}
server/lib/model.js
- This will cover common db operations for a node type. Change to your liking :)
var util = require('util')
var db = require('./db.js')
exports.node = function (nodeName, extras) {
var nodeNameLower = nodeName.toLowerCase()
var Model = {
all: function () {
return db.nodesWithLabel_p(nodeName)
},
findBy: function (attrs) {
return db.find_p(attrs, nodeName)
.then( exports.firstResult(Model) )
},
create: save,
update: function (attrs) {
if (attrs.id === null && attrs.id === undefined) {
throw new InvalidArgument("You must provide an id to update.")
}
return save(attrs, 'update')
},
updateOrCreateBy: function (attrName, attrs) {
return Model.findBy({ [attrName]: attrs[attrName] })
.then(
modelData => Model.update( Object.assign(modelData, attrs) )
)
.catch( Model.NotFound, save.papp(attrs, 'create') )
}
}
//
// Common Errors
//
Model.NotFound = function NotFound(details) {
Error.captureStackTrace(this, this.constructor)
this.name = 'NotFound'
this.message = nodeNameLower + '_not_found'
if (details) this.details = details
}
util.inherits(Model.NotFound, Error)
Model.InvalidArgument = function InvalidArgument (message) {
Error.captureStackTrace(this, this.constructor)
this.name = 'InvalidArgument'
this.message = message
}
util.inherits(Model.InvalidArgument, Error)
return Object.assign(Model, extras)
function save (attrs, type) {
if (attrs.id !== null && attrs.id !== undefined) {
var cleanAttrs = Model.cleanAttrs( attrs )
cleanAttrs.updated_at = new Date()
return db.call_p(
db.operation( 'node/' + attrs.id + '/properties', 'PUT', cleanAttrs )
)
.return( Object.assign(cleanAttrs, { id: attrs.id }) )
}
else {
attrs.created_at = new Date()
return db.save_p( attrs, nodeName )
}
}
}
exports.firstResult = function (Model) {
return function (models) {
return (models.length === 0) ? Promise.reject(new Model.NotFound()) : models[0]
}
}
server/models/user.js
- An example of a User model.
var db = require('../lib/db')
var Model = require('../lib/mode')
var User = module.exports = Model.node('User', 'users', {
signIn: function (username, password) {
return User.findBy({ username: username })
.then(function(user) {
// In a real app the user's password would be encrypted
if (user.password === password) {
return user
}
else {
return Promise.reject(new User.InvalidCredentials())
}
})
},
// Some queries will require custom Cypher
mutualFriends: function (userId_1, userId_2) {
var query = `
MATCH
(a:User)-[:FRIEND_OF]-(mutual:User)-[:FRIEND_OF]-(b:User)
WHERE
id(a) = { userId_1 } AND id(b) = { userId_2 }
RETURN mutual
`
return db.query_p(query, { userId_1: userId_1, userId_2: userId_2 })
},
})
// Custom error specific to User model
User.InvalidCredentials = function InvalidCredentials() {
Error.captureStackTrace(this, this.constructor)
this.name = 'InvalidCredentials'
this.message = modelName + ': not found.'
}
util.inherits(User.InvalidCredentials, Error)