brikteknologier / seraph-model

thin model layer for seraph/neo4j (node.js)
MIT License
111 stars 28 forks source link

Save with composition creates extra empty nodes #106

Closed JosephScript closed 8 years ago

JosephScript commented 8 years ago

I have a few objects that are composed. When I save them I'm getting weird empty duplicates that don't seem possible. I'm wondering if I'm doing something wrong?

character.js

var db = require('../lib/neo4j');
var model = require('seraph-model');
var characterClass = require('./characterClass');
var nodeUuid = require('node-uuid');

var character = model(db, 'character');

character.fields = ['name', 'uuid'];
character.setUniqueKey('uuid');
character.useTimestamps();
character.compose(characterClass,'characterClass','has_class', {many: false});

character.on('prepare', function(object, callback) {
  if (!object.uuid) {
    object.uuid = nodeUuid.v4();
  }
  return callback(null, object);
});

character.schema = {
  name: {type: String, required: true}
};

module.exports = character;

characterClass.js

var db = require('../lib/neo4j');
var model = require('seraph-model');
var nodeUuid = require('node-uuid');
var spells = require('./spells');

var characterClass = model(db, 'characterClass');

characterClass.fields = ['name', 'uuid'];
characterClass.setUniqueKey('uuid');
characterClass.useTimestamps();
characterClass.compose(spells, 'spells', 'has_spell', {many: true});

characterClass.on('prepare', function(object, callback) {
  if (!object.uuid) {
    object.uuid = nodeUuid.v4();
  }
  return callback(null, object);
});

characterClass.schema = {
  name: {type: String, required: true}
};

module.exports = characterClass;

spells.js:

var db = require('../lib/neo4j');
var model = require('seraph-model');
var nodeUuid = require('node-uuid');

var spell = model(db, 'spell');

spell.fields = ['name', 'uuid'];
spell.setUniqueKey('uuid');
spell.useTimestamps();

spell.on('prepare', function(object, callback) {
  if (!object.uuid) {
    object.uuid = nodeUuid.v4();
  }
  return callback(null, object);
});

spell.schema = {
  name: {type: String, required: true}
};

module.exports = spell;

This is the actual save function:

var express = require('express');
var router = express.Router();
var characters = require('./models/characters');

router.post('/', function(req, res, next) {

var character = { 
  name: 'Gandalf the Grey',
  characterClass:
   { 
      name: 'Wizard',
      spells: [{
          name: 'Flood'
        }, {
          name: 'Fireworks'
        }, {
          name: 'You shall not pass!'
      }]
    } 
 };

  async.waterfall([
    function(callback) {
      characters.save(character,
        function(err, result) {
          return callback(err, result);
        });
    },
    function(result, callback) {
      // relate it back to the user as a player
      db.relate(req.user.id, 'owns_character', result,
       function(err, relationship) {
        return callback(err, result);
      });
    }
  ], function(err, node) {
    if (err) {
      return next(err);
    }
    res.send(node);
  });
});

module.exports = router;

Everything works as expected, except I get weird empty nodes in the result:

{
  "updated":1457715310574,
  "created":1457715310574,
  "name":"Gandalf the Grey",
  "uuid":"5110c3bc-b796-43bf-94c7-be2ee23d5038",
  "id":114,
  "characterClass":[
    {
      "updated":1457715310574,
      "created":1457715310574,
      "name":"Wizard",
      "uuid":"24a4dc08-a6bf-4ef8-8e6b-d120829fc13a",
      "id":119,
      "spells":[{
        "updated":1457715310574,
        "created":1457715310574,
        "name":"Flood",
        "uuid":"ee97b3f2-d011-4c37-8f80-2db42df931c3",
        "id":115,
        "_rel":{}
      },{
        "updated":1457715310574,
        "created":1457715310574,
        "name":"Fireworks",
        "uuid":"a8996356-faa5-4715-a4e2-4796b352bdfd",
        "id":116,
        "_rel":{}
      },{
        "updated":1457715310574,
        "created":1457715310574,
        "name":"You shall not pass!",
        "uuid":"b94c926e-1d20-4abc-95e1-8c02f06f4c31",
        "id":117,
        "_rel":{}
      },
      {
        "updated":1457715310574,
        "created":1457715310574,
        "id":118,
        "_rel":{}
      }
    ],
    "_rel":{}
    },
    {
      "updated":1457715310574,
      "created":1457715310574,
      "id":120,
      "_rel":{}
      }
    ]
  }

Any ideas? Thanks in advance!

JosephScript commented 8 years ago

I'm running Neo4j v2.3.2 on Node v5.7.0.

JosephScript commented 8 years ago

I cloned the repo and tests run fine, so it's not my versions.

For now I made a workaround where I just use excludeCompositions: true, and save the composed models in a second and third query. Inefficient and ugly, but it's working at least.

If anyone can help me track down the source of these extra nodes I'd very grateful!

jonpacker commented 8 years ago

Hey dude, are you still having this problem? It's super strange. I copied and pasted all your code and ran it locally, and I didn't get any ghost nodes at all:

{
  "uuid": "e335be61-7193-4f4a-bb51-daa19f0f1b64",
  "updated": 1469793669046,
  "created": 1469793669046,
  "name": "Gandalf the Grey",
  "id": 173714,
  "characterClass": {
    "uuid": "43e59500-ddf5-4e1e-8d54-8233102e4360",
    "updated": 1469793669046,
    "created": 1469793669046,
    "name": "Wizard",
    "id": 173718,
    "spells": [
      {
        "uuid": "67289a0f-f81b-43d8-a48a-2636b04afa1b",
        "updated": 1469793669046,
        "created": 1469793669046,
        "name": "Flood",
        "id": 173715,
        "_rel": {}
      },
      {
        "uuid": "b4a4dedb-6ca3-4e22-b1ce-750dd0578d89",
        "updated": 1469793669046,
        "created": 1469793669046,
        "name": "You shall not pass!",
        "id": 173717,
        "_rel": {}
      },
      {
        "uuid": "5ea96971-cfcd-4722-a970-e3699d130cb3",
        "updated": 1469793669046,
        "created": 1469793669046,
        "name": "Fireworks",
        "id": 173716,
        "_rel": {}
      }
    ],
    "_rel": {}
  }
}

seraph-model@0.8.3 seraph@0.15.2

Please reopen if you're still having problems with this!

JosephScript commented 7 years ago

Thanks @jonpacker for checking into it. I ended up disabling save with compositions, and then manually created the relationships using seraph.relate. I've also since then updated seraph and seraph-model. I will try it out later and if it's still an issue I'll let you know. But since you got it to work, I'll assume it is fixed for now.

Thanks again.