Mongoose: Recursive Schema type makes an error

Created on 8 Jun 2015  Â·  10Comments  Â·  Source: Automattic/mongoose

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var ReplySchema = new Schema({
nickName: { type: String, unique: true, required: true },
content: String,
replies: [ReplySchema]
}, { _id: true });

~node_modulesmongooselibschema.js
:298
throw new TypeError('Invalid value for schema Array path '+ prefix + ke ^ TypeError: Invalid value for schema Array pathreplies`
at Schema.add (~node_modulesmon
gooselibschema.js:298:13)
at new Schema (~node_modulesmon
gooselibschema.js:88:10)
at Object. (~modelsr
eply.js:4:19)

help

Most helpful comment

That's just how JavaScript works -

var ReplySchema = new Schema({
nickName: { type: String, unique: true, required: true },
content: String,
replies: [ReplySchema]
}, { _id: true });

ReplySchema is undefined when you say replies: [ReplySchema]. Do this instead:

var ReplySchema = new Schema({
nickName: { type: String, unique: true, required: true },
content: String
}, { _id: true });

ReplySchema.add({ replies: [ReplySchema] });

That will give you the desired behavior.

All 10 comments

just add

var ReplySchema = {};

ReplySchema = new Schema ...

removed that error but it turns out to be [{}]

That's just how JavaScript works -

var ReplySchema = new Schema({
nickName: { type: String, unique: true, required: true },
content: String,
replies: [ReplySchema]
}, { _id: true });

ReplySchema is undefined when you say replies: [ReplySchema]. Do this instead:

var ReplySchema = new Schema({
nickName: { type: String, unique: true, required: true },
content: String
}, { _id: true });

ReplySchema.add({ replies: [ReplySchema] });

That will give you the desired behavior.

@vkarpov15 thank you for this great kindness

It should work. Please post on github with a code sample demonstrating your
issue.

On Mon, Oct 31, 2016 at 9:19 AM, Kieran Sedgwick [email protected]
wrote:

@vkarpov15 https://github.com/vkarpov15 Is this behaviour supported in
mongoose 3.8? I'm doing something similar to OP's example, but I keep
getting nested schema errors.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Automattic/mongoose/issues/3056#issuecomment-257340814,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABi5KaCmSMZw7MJKD7sV3a_AS7hx1Yczks5q5hUjgaJpZM4E8AvU
.

i created a recursive schema attribute as per above example - ReplySchema.add({ replies: [ReplySchema] });

My question now is, i see "replies" having "_id"'s created. Can we eliminate the "_id" creation in recursive attributes ? is there a way ?

@prema6 When your nested schema is recursive, the nested path's schema is a reference to the top level schema.

So, any changes you make to the nested path's schema will also apply to the top level schema
( e.g. if you remove the _id path from the replies's schema with ReplySchema.remove('replies._id'), it will also remove the _id property from the top level schema.).

This gist shows the only way I could come up with to:

  1. Only create one schema
  2. Get recursion
  3. remove the _id property only from nested objects but still get a top level _id

@vkarpov15 is there a better way to do this?

Thank you for the response.

@lineus @prema6

~ReplySchema.add({ replies: [ReplySchema.clone().remove('_id')] });~

~See clone and remove in docs.~

See @lineus 's post below for a correct example

@vkarpov15 that was one of the methods I tried before I arrived at a similar solution in my gist above ( which uses the same methods ).

Currently Schema.prototype.remove() and Schema.prototype.add() don't return the Schema instance, but it's a one-line fix in each function if you think they should. I put in a PR for it, I think that it makes sense for both methods to return the instance.

It's also worth mentioning that in order to get the intended recursion, i.e. replies[n].replies[n].replies[n]..., the schema in the replies path needs to
point to itself ( line 3 below ).

e.g.

const repliesSchema = replySchema.clone();
repliesSchema.remove('_id');
repliesSchema.add({ replies: [repliesSchema] });

replySchema.add({ replies: [repliesSchema]});

using the inline syntax above with clone(), remove() and add() will only allow one level of recursion as opposed to many-infinity ( manfinity? )

@lineus that's a good point. I'll edit my comment to cross out my response, your response is more correct.

Was this page helpful?
0 / 5 - 0 ratings