Skip to content

ID values incorrectly stored as plain strings in relation tables for mongodb #274

Description

@innerdaze

Outline

When creating many-many relations between models for a mongodb data source, entries are stored in the relation table as per this example:

{ 
  "_id" : ObjectId("537b7f5eb723553355816de6"),
  "partId" : "5379f3444d596bea29987bef",
  "jobId" : "5379e59d6fd568ba272a940c"
}

The job record in referred to in this record is:

{
  "_id" : ObjectId("5379e59d6fd568ba272a940c"),
  "title" : "test", 
  ...
}

When querying the relation, a query such as job.parts() will return an empty array because the job._id property with a value of ObjectId("5379e59d6fd568ba272a940c") will not match the jobId property with a value of "5379e59d6fd568ba272a940c".

The first example (the relation object) is always created this way when using either of the following methods:

job.parts.add(part, cb);

or

var PartJob = Part.relations.job.modelThrough;

PartJob.create({
    partId: "5379f3444d596bea29987bef",
    jobId: "5379e59d6fd568ba272a940c"
}, cb);

Workaround

As it stands, the only way found to make a working many-many relation is to use the following method:

var ObjectID = require('mongodb').ObjectID;
var PartJob = Part.relations.job.modelThrough;

PartJob.create({
    partId: ObjectID("5379f3444d596bea29987bef"),
    jobId: ObjectID("5379e59d6fd568ba272a940c")
}, cb);

This creates the relation object:

{ 
  "_id" : ObjectId("537b7f5eb723553355816de6"),
  "partId" : ObjectId("5379f3444d596bea29987bef"),
  "jobId" : ObjectId("5379e59d6fd568ba272a940c")
}

Proposed Solution

Whilst this creates a usable many-many relation, it creates an extra step in the process and invalidates the job.parts.add method, so the casting of the the string ID to an ObjectID should probably occur behind the scenes. This would also avoid having to change the existing public API.

Also (and this should probably have it's own github issue), if you wanted to create a many-many relation over a REST API, it's more efficient to simply pass the IDs of the object you wish to connect and create the relation object directly onto the relation table.

This (as Raymond has pointed out) is a rather hacky approach and in terms of providing a clean fix for the above issue becomes unfeasible as you would still be forced to manually cast the ID properties.

I propose a static method for each relationship on each model class for creating a relation that simply takes the 2 IDs to create a relation for. With this approach, the static method could perform the ID casting without the developer having to concern themselves with it.

For example:

var ObjectID = require('mongodb').ObjectID;
var PartJob = Job.relations.part.modelThrough;

Job.attachPart = function(jobId, partId, callback){

    PartJob.create({
        partId: ObjectID(partId),
        jobId: ObjectID(jobId)
    }, function(err, result){
        if (err) {
            callback(err);
        } else {
            callback(null, result);
        }
    });

};

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions