Модель Мангуста.поиск не является функцией — сбой в одном случае работает в другом

#node.js #mongoose #mongoose-schema #mongoose-middleware

#node.js #мангуст #мангуста-схема #mongoose-промежуточное программное обеспечение

Вопрос:

У меня есть два похожих дерева отношений родитель-потомок в моей модели данных, и я использую промежуточное программное обеспечение Mongoose для обработки каскада удалений.

Первая иерархия представлена следующим образом:

иерархия блога

 //blog.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.js');
var Entry = require('./entry.js');
var Follower = require('./follower.js');

var Blog = new Schema({
    author: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    name: {
        type: String,
        required: true
    },
    headerImageUrl: String,
    description:  {
        type: String,
        required: true
    }
}, {
    timestamps: true
});

Blog.pre('remove', function(next) {
    Entry.find({"blogId": this._id})
        .exec(function(err, entries) {
            console.log("found entries "   entries);
            for(var i = entries.length -1; i >= 0; i--) {
                entries[i].remove();
            }
        });
    Follower.remove({"blogId": this._id}).exec();
    next();
});

module.exports = mongoose.model('Blog', Blog);


//entry.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Blog = require('./blog.js');
var Comment = require('./comment.js');

var Entry = new Schema({
    blogId: {
        type: Schema.Types.ObjectId,
        ref: 'Blog'
    },
    title: String,
    thumbnailUrl: String,
    content: String
}, {
    timestamps: true
});

Entry.pre('remove', function(next) {
    Comment.remove({"entryId": this._id}).exec();
    next();
});

module.exports = mongoose.model('Entry', Entry);



//comment.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.js');
var Entry = require('./entry.js');
var Post = require('./post.js');

var Comment = new Schema({
    text:  {
        type: String,
        required: true
    },
    postedBy:  {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    parentComment: this,
    entryId: {
        type: Schema.Types.ObjectId,
        ref: 'Entry'
    },
    postId: {
        type: Schema.Types.ObjectId,
        ref: 'Post'
    },
    type: {
        type: String,
        enum: ['BLOG', 'FORUM', 'COMMENT'],
        required: true
    }
}, {
    timestamps: true
});

module.exports = mongoose.model('Comment', Comment);
  

В этом случае, когда remove вызывается для экземпляра blog, Blog.pre('remove'... функциональность выполняет то, для чего она предназначена, и очищает все дочерние элементы экземпляра blog.
Вызывающий код выглядит следующим образом:

 blogRouter.route('/:blogId')

//delete a specific blog by blog id:    [OWNER OR ADMIN USER]
.delete(Verify.verifyOrdinaryUser, Verify.verifyBlogOwnerOrAdmin, function(req, res, next) {
    Blog.findById(req.params.blogId, function(err, blog) {
        if(err) return next(err);
        blog.remove();
        res.json(blog);
    });
});
  

Я делаю то же самое для второй иерархии, визуально представленной здесь: иерархия форума и со следующим кодом:

 //forum.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.js');
var Post = require('./post.js');
var Subscription = require('./subscription.js');

var Forum = new Schema({
    title: {
        type: String,
        required: true
    },
    description: String,
    moderators: [
        {
            type: Schema.Types.ObjectId,
            ref: 'User'
        }
    ]
}, {
    timestamps: true
});

Forum.pre('remove', function(next) {
    Post.find({"forumId": this._id})
        .exec(function(err, posts) {
            console.log("found posts "   posts);
            for(var i = posts.length -1; i >= 0; i--) {
                posts[i].remove();
            }
        });
    Subscription.remove({"forumId": this._id}).exec();
    next();
});

module.exports = mongoose.model('Forum', Forum);


//post.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.js');
var Forum = require('./forum.js');
var Comment = require('./comment.js');

var Post = new Schema({
    createdBy: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    postText: {
        type: String,
        required: true
    },
    forumId: {
        type: Schema.Types.ObjectId,
        ref: 'Forum'
    },
}, {
    timestamps: true
});

Post.pre('remove', function(next) {
    Comment.remove({"postId": this._id}).exec();
    next();
});

module.exports = mongoose.model('Post', Post);


//comment.js [SAME AS INCLUDED ABOVE]
  

Но в этом случае, когда remove вызывается на экземпляре форума, Forum.pre('remove'... функциональность вызывает ошибку: TypeError: Post.find не является функцией. Ошибка выдается при forum.js строка 24 (вторая строка в блоке Forum.pre(…))

Вызывающий код выглядит следующим образом:

 forumRouter.route('/:forumId')

//delete forum by id:  [ADMIN]
.delete(Verify.verifyOrdinaryUser, Verify.verifyAdmin, function(req, res, next) {
    Forum.findById(req.params.forumId, function(err, forum) {
        if(err) return next(err);
        forum.remove();
        res.json(forum);
    });
});
  

Хотя я обнаружил, что эта ошибка была вызвана в моих онлайн-исследованиях здесь и в других местах, причинами были неправильно экспортированные модели или неправильно определенные схемы. Схема Post успешно используется во всем остальном моем коде без проблем, только этот вызов Post.find вызывает ошибку. И на самом деле, мой код postRouter успешно вызывает следующее:

 postRouter.route('/')

// retrieve all forum posts:  [ALL USERS]
.get(function(req, res, next) {
    Post.find({})
        .populate({
            path: 'forumId',
            model: 'Forum',
            populate: {
                path: 'moderators',
                model: 'User'
            }
        })
        .populate('createdBy')
        .exec(function(err, posts){
            if(err) return next(err);
            res.json(posts);
        });
});
  

Комментарии:

1. вы зарегистрировали, какой пост на самом деле находится в вашей модели форума?

2. Да, когда я делаю вызов для получения всех сообщений на основе идентификатора форума с помощью моего REST API, я вижу правильную связь между форумом и сообщением, и когда я регистрирую данные post, полученные к Post.find({"forumId": ObjectId("<<forum object id>")}) тому времени, я получаю ожидаемые данные. Выдает ошибку только при вызове из pre('remove'... функции.

3. Это не то, что я спрашивал. Вы когда-нибудь делали console.log(Post) прямо перед строкой, где Post.find не определено?

4. Понял. Только что сделал, и кажется, что Post ведет себя неправильно. При выполнении console.log (Post) {} Однако, когда я выполняю console.log (запись) в другом рабочем примере, я получаю function model(doc, fields, skipId) { if (!(this instanceof model)) { return new model(doc, fields, skipId); } Model.call(this, doc, fields, skipId); }

5. Это все еще не решает основную проблему… отношение родитель-потомок одинаково в обоих случаях, определение схемы по существу одинаково в обоих случаях, вызывающий код одинаков в обоих случаях, но в одном случае он работает, а в другом выдает ошибку.