0

Here is my schema:

var A = new Schema({
    active: Boolean
  , containers: [{
         b: { type: ObjectId, ref: 'B' }
    }]
})

var B = new Schema({
    c: { type: ObjectId, ref: 'C' }
  , d: { type: ObjectId, ref: 'D' }
})

var C = new Schema({ })

var D = new Schema({ })

Basically an A has an array of containers that have a reference to a B, and a B has a reference to a C and a D.

Now I have the id of a C and I need a set of D that are used by active As. Is this even possible? Should I change the schema in some way?

EDIT: real schema here

 //Mashup has a number of Containers (containerSchema is a sub-doc)
    //so that the same Component could belong to two different Containers
    var containerSchema = new Schema({
          pos: { top: Number, left: Number }
        , size: { width: Number, height: Number }
        , component: { type: ObjectId, ref: 'Component' }
    })

    var mashupSchema = new Schema({
          name: String
        , desc: String
        , size: { width: Number, height: Number }
        , active: Boolean
        , containers: [containerSchema]
    })

    //I am using 'mongoose-schema-extend' to inherit from componentSchema (waiting for the new PR)
    var componentSchema = new Schema({
          name: String
        , desc: String
    }, { collection : 'components', discriminatorKey : '_type' })

    //now the various components
    var imageComponentSchema = componentSchema.extend({
          url: String
    })

    var textComponentSchema = componentSchema.extend({
          text: String
    })


    var htmlComponentSchema = componentSchema.extend({
          html: String
    })

    //this particular component needs a page and a selector
    //(which could live outside it and belong to multiple components)
    var webComponentSchema = componentSchema.extend({
          page: { type: ObjectId, ref: 'Page' }
        , selector: { type: ObjectId, ref: 'Selector' }
    })

    var pageSchema = new Schema({
          name: String
        , desc: String
        , url: String
        , active: { type: Boolean, default: false }
    })

    var selectorSchema = new Schema({
          desc: String
        , url: String
        , cssPath: String
    })

    ///MODELS
    var Mashup = mongoose.model("Mashup", mashupSchema)
    var Component = mongoose.model("Component", componentSchema)
    var ImageComponent = mongoose.model("ImageComponent", imageComponentSchema)
    var TextComponent = mongoose.model("TextComponent", textComponentSchema)
    var HtmlComponent = mongoose.model("HtmlComponent", htmlComponentSchema)
    var WebComponent = mongoose.model("WebComponent", webComponentSchema)
    var Page = mongoose.model("Page", pageSchema)
    var Selector = mongoose.model("Selector", selectorSchema)
Aziz Shaikh
  • 16,245
  • 11
  • 62
  • 79
fusio
  • 3,595
  • 6
  • 33
  • 47

2 Answers2

1

You think too relational! Right now you, I don't think you can do this efficiently as you will have to:

  • find all B's that have c: {id}
  • find all A's that have a b that is the set of the result from query 1 and are Active
  • find out which B's belong to the IDs you've found in the previous query
  • find out which D's belong to the B's you've found

I think you should most definitely denormalise your schema here. For example, you can put all of the above in one document:

{
    Active: true,
    containers: [ // B's
        { c: [
            { _id: X, field1: foo },
            { _id: X, field1: foo },
        ] },
        { d: [
            { _id: X, field1: foo },
            { _id: X, field1: foo },
        ] }
    ]
}

And then you can just do it with one query:

db.collection.find(
    { "container.c._id" : your_id, Active: true }, // query
    { "container.d" : 1 } // projection
);
Derick
  • 35,169
  • 5
  • 76
  • 99
  • But I still need B.. I want to be able to query for all the B. The client needs to be able to create a new A, then select a B from a list and add it to A. I guess I could have a B and instead of pushing it, extract the C and D and push those.. Mhh – fusio Aug 15 '13 at 16:04
  • You are 100% right, sorry about that example. [Here](https://groups.google.com/forum/#!topic/mongoose-orm/XUENp02gGWE) I posted a real example. Thanks :) – fusio Aug 15 '13 at 22:27
0

Ended up changing the DB schema completely. Closing.

fusio
  • 3,595
  • 6
  • 33
  • 47