Proper way to make a mongoose schema for a dynamic number of key/value pairs
Asked Answered
G

2

8

I have a word counting function that returns an object with a set of key value pairs. Something like this: {a: 4, tale: 3, of: 8, two: 3, cities: 3 }

Obviously this object can be of varying lengths and have different key/value pairs. I'd like to add this data to an 'article' document in Mongodb. Using mongoose.js this is the best schema I can come up with. I'm concerned that mongo is creating a ton of "Word" documents with one key/value pair and an id. Is there a better way?

in /models/article.js

mongoose.Schema({
  wordcounts: [wordSchema]
})

in /models/word.js

mongoose.Schema({
  word: String,
  count: Number
})

So the it would end up looking like:

[{
_id: 3980923urjf0e232902343252,
wordcounts: [
  {_id: 2039840297502938402934, word: "Apple", count:3}, 
  {_id: 20398sdfsdfsdfaaa4asd3, word: "Banana", count:5}
  ]
}]

Is there a better way?

Gosplan answered 13/11, 2015 at 0:35 Comment(0)
B
10

If you don't need indexing, you can use Schema.Types.Mixed (see: http://mongoosejs.com/docs/schematypes.html )

Otherwise, you don't have to define a sub-collection, as you could just define it as:

mongoose.Schema({
  wordcounts: [{
    word: String,
    count: Number
  }]
})
Bowline answered 13/11, 2015 at 0:50 Comment(2)
Thanks I will try it out!Gosplan
This works! It also assigns an id to each word document in the wordcounts array.Gosplan
E
0

Mongoose now has a Map schema type based on JavaScript's Map class. If you don't need an _id for each key-value pair you could do:

mongoose.Schema({
  wordcounts: {
    type: Map,
    of: String | Number
  }
})

doc.wordcounts.get('Apple') === 3
doc.wordcounts.get('Banana') === 5

Reference: https://mongoosejs.com/docs/schematypes.html#maps

Eleusis answered 18/1 at 13:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.