Skip to content
This repository has been archived by the owner on Jan 25, 2023. It is now read-only.

Seletive Models, delete documents and slow #1

Open
gabrielmancini opened this issue Apr 26, 2013 · 11 comments
Open

Seletive Models, delete documents and slow #1

gabrielmancini opened this issue Apr 26, 2013 · 11 comments

Comments

@gabrielmancini
Copy link

Hi Philipp,

Before at all, congrats for your great job on this project, its awesome, be sides coffescripe 3:D.

Your idea makes all sens, join together the powerful mongo document and neo4j graph relations.

-Do you have some gotchas to use mongraph to use selective mongoose models?
-When i delete a document on mongo the node is delete to?
-I feel a little slow down in my tests ween i start mongraph, i need to tuning something?

thanks for coding this

cheers

ps: sorry about my english :-/

@pstaender
Copy link
Owner

Hi Gabriel,

nice to hear that you like the idea and want to use it :)

  1. it's working together with the usual mongoose - you can use mongoose like you used to... there are (currently) a save+delete hook, a schema extension and the relationship methods extended on (I hope that answered your question)

  2. -> yes, if you delete a document, it will delete (by default) the corresponding node

  3. Performance is definitely an issue, so this should have nothing to do with your db setup...

The main problem is that for each document has to be loaded the corresponding node (and the other way round) from neo4j / mongodb. So this design construct doubles the requests on each record. If you have now enabled the populate documents for relationships (it's enabled by default and is too convenient to turn it off ^^) for each relationship will be loaded all related documents.

Currently each document is queried separately... that is going to be changed to "query all documents of one collection at once" in one of the next releases.

Beside that I see currently not much room for performance improvement. But maybe some benchmark tests would help to find bottlenecks and make different operations more comparable.

Cheers
Philipp

@pstaender
Copy link
Owner

I added benchmark tests that shows that mongraph is much slower than mongoose:

### DELETING RECORDS

* deleting native mongodb documents x 743 ops/sec ±4.00% (68 runs sampled)
* deleting mongoose documents x 447 ops/sec ±1.66% (80 runs sampled)
* deleting neo4j nodes x 151 ops/sec ±20.24% (63 runs sampled)
* deleting mongraph documents x 50.81 ops/sec ±20.99% (73 runs sampled)

**Fastest** is deleting native mongodb documents

**Slowest** is deleting mongraph documents

But as you can see the neo4j nodes are mostly the bottleneck. Maybe an option to make deleting corresponding nodes as well and/or deleting node asynchronously would "solve" the »waiting for neo4j to finish the deletion job« problem...

@gabrielmancini
Copy link
Author

Hi Philipp @pstaender ,

First of all, thanks for your answer and benchmark!

About the first question

Q -> Do you have some gotchas to use mongraph to use selective mongoose models?
A-> (it's working together with the usual mongoose - you can use mongoose like you used to... there are (currently) a save+delete hook, a schema extension and the relationship methods extended on (I hope that answered your question)
Q2-> I think in my question i was a little abstract, i have 30 model on mongoose, but i just have interest in relation 5 and some cases auto relation, so, there is some gotcha how i configure mongraph to act only in some models? by the way ,the remove hook has some problem when i config the mongraph on specific model the Model.post('remove') stop work

About the 3 Question,

You can think about use this guy to comunicate with neo4j, https://github.com/scttnlsn/mubsub i think that way u can add ou delete node asynchronously. what you think?

sorry about comment in a close issue :-/

@pstaender
Copy link
Owner

no problem - i closed too soon and you problem is correct (I understood it the wrong way ^^). the problem is, once a schema is compiled in mongoose, you can't recompile it, so the remove hook is not replaceable. but according to your first suggestion to make graphability optional could be a good way to handle with that for each model.

would you say it would be a good way to define that in your schema, s.th. like:

schema =  {
    name: String,
    ...
// enables by default all extensions (schema + middleware/hooks)
    graphability: true,
// or specific ones
    graphability: {
      schema: true,
      middleware: [ 'preRemove', 'preSave' ]
    }
  }

what do you think?

@pstaender pstaender reopened this Apr 30, 2013
@pstaender
Copy link
Owner

Here is what I found about problems with overwriting middleware: Automattic/mongoose#1251
Anyway, it's seems to work to use many preSave hooks, but only on preRemove hook on mongoose. Now you can switch it by defining as schema option (by default it's activated):

schema  = new mongoose.Schema({ name: String })
schema.set('graphability', false) #disable schema extension and middleware
# or set specific options via json
schema.set('graphability', { middleware: { preSave: true, preRemove: false } }) # disables preRemove hook

See more on the tests @:

  it 'expect that schema extensions and hooks can be optional', (done) ->

Channels and listeners sound interesting... bu not sure that it makes it more comfortable / easier to handle…
Instead you can could delete the node(s) on bigger operations by yourself (async) and remove a document (it will skip automatically the remove process if it can't find a node id). But it's an interesting idea, maybe we can implement that later.

@gabrielmancini
Copy link
Author

Hi @pstaender ,

That's a great solution, i will try to implement in my app, stay this issue open i will back with the feedback.
But the problem occur on postRemove, please take a look.
So, in my 25 mongoose models how i don't want create a relationship between then, i set this guy: schema.set('graphability', false) and that's it. amazing ;-)

Off course we can implement the asinc option :-D, i made something like that, but using ES and a plugin river in here take a look
taterbase/mongoosastic#61

but the mongraph is in coffescript so it can be more harder for me :-/ but not impossible, lets go! :-D

@gabrielmancini
Copy link
Author

Hi @pstaender ,

I think i m doing something whrong here, can u help me?

I load my models that way

var mongoose = require('mongoose'),
    fs       = require('fs'),
    di       = require('injector'),
    mongraph     = require('mongraph'),
    neo4j        = require('neo4j');    ;

// Load Models
module.exports = function (app) {

  mongraph.init({
    neo4j: new neo4j.GraphDatabase(app.settings.config.graphdb),
    mongoose: mongoose
  });

    // Connect db
    mongoose.connect(app.settings.config.db);

    // Bootstrap models
    fs.readdirSync(__dirname).forEach(function (file) {
        if (file !== __filename.replace(__dirname + '/', '') && (file !== 'plugins')) {
      di.process(require('./'+file));
      console.log('load model: ', file);
    }
    });

  function handleModelError(err) {
    console.log('err: %s', err);
  }

    //Register Mongoose Modules on di
    for(var k in mongoose.models) {
    //Add Plugin to ElasticSearch

    var model = mongoose.models[k];
    model.river();
    model.on('error', handleModelError);

        di.register(k, model);
    }
};

and there is an model i dont wanna create relation on neo4j so i do this:

// Tag schema
var mongoose      = require('mongoose'),
    mongoosastic  = require('mongoosastic');

module.exports = function(app) {
  var Schema = mongoose.Schema;

  // Schema
  var TagSchema = new Schema({
    name: {type : String, 'default' : '', trim : true, required: true},
  });

  //Disabled mongraph
  TagSchema.set('graphability', false);

  // Plugins
  TagSchema.plugin(mongoosastic, app.settings.config.mongoosastic);
  mongoose.model('Tag', TagSchema);
};

but when i run my tests, on neo4j db the Node tag was created :-/ what i do wrong?

@pstaender
Copy link
Owner

mmh, can't see a mistake... are you using the latest version? Have you tried it without the plugin? Is the node attached to the document?

In the tests it's done the following way:

var Guitar, guitar, schema;

schema = new mongoose.Schema({
  name: String
});

schema.set('graphability', false);

Guitar = mongoose.model("Guitar", schema);

guitar = new Guitar({
  name: 'Fender'
});

guitar.save(function(err, doc) {
  expect(err).to.be(null);
  expect(doc._node_id).to.be(void 0);
  return doc.getNode(function(err, node) {
    expect(err).not.to.be(null);
    return expect(node).to.be(null);
  });
});

Cheers Philipp

@gabrielmancini
Copy link
Author

AHHH!!!! Dammed, its a version, sorry about that....

i still have problems with remove documents,
the hook do not work and the node still in neo4j. :-/

@gabrielmancini
Copy link
Author

Hi @pstaender

when i set schema.set('graphability', true);

i had this error:
what i do wrong?

/home/gabriel/Documents/github/bilgow/api/node_modules/mongraph/lib/mongraphMongoosePlugin.js:28
  if ((_ref3 = (_base2 = schemaOptions.graphability.middleware).preRemove) == 
                                                               ^
TypeError: Cannot read property 'preRemove' of undefined
    at module.exports.mongraphMongoosePlugin (/home/gabriel/Documents/github/bilgow/api/node_modules/mongraph/lib/mongraphMongoosePlugin.js:28:64)
    at Schema.plugin (/home/gabriel/Documents/github/bilgow/api/node_modules/mongoose/lib/schema.js:535:3)
    at Mongoose._applyPlugins (/home/gabriel/Documents/github/bilgow/api/node_modules/mongoose/lib/index.js:322:12)
    at Mongoose.model (/home/gabriel/Documents/github/bilgow/api/node_modules/mongoose/lib/index.js:259:12)
    at Function.module.exports (/home/gabriel/Documents/github/bilgow/api/models/user.js:153:12)
    at Object.global.Injector.process (/home/gabriel/Documents/github/bilgow/api/lib/injector.js:9:12)
    at module.exports.model (/home/gabriel/Documents/github/bilgow/api/models/index.js:22:10)
    at Array.forEach (native)
    at Function.module.exports (/home/gabriel/Documents/github/bilgow/api/models/index.js:20:28)
    at Object.global.Injector.process (/home/gabriel/Documents/github/bilgow/api/lib/injector.js:9:12)
    at Object.<anonymous> (/home/gabriel/Documents/github/bilgow/api/server.js:23:4)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:362:17)
    at require (module.js:378:17)
    at Object.<anonymous> (/home/gabriel/Documents/github/bilgow/api/test/api/v1/functional/user.test.js:5:9)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:362:17)
    at require (module.js:378:17)
    at Mocha.loadFiles (/home/gabriel/Documents/github/bilgow/api/node_modules/mocha/lib/mocha.js:152:27)
    at Array.forEach (native)
    at Mocha.loadFiles (/home/gabriel/Documents/github/bilgow/api/node_modules/mocha/lib/mocha.js:149:14)
    at Mocha.run (/home/gabriel/Documents/github/bilgow/api/node_modules/mocha/lib/mocha.js:305:31)
    at Object.<anonymous> (/home/gabriel/Documents/github/bilgow/api/node_modules/mocha/bin/_mocha:327:7)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback (node.js:245:9)

@pstaender
Copy link
Owner

@gabrielmancini , it's seems that there is middleware is set as an undefined but it should be set as {} by default

  # set default values, both hooks
  schemaOptions.graphability.middleware = {} if schemaOptions.graphability.middleware and typeof schemaOptions.graphability.middleware isnt 'object'
  schemaOptions.graphability.middleware.preRemove ?= true
  schemaOptions.graphability.middleware.preSave   ?= true 

Please try to set it as true in the options ( s.th. like { graphibility = true } )

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants