Как добавить метод подсчета в Bookshelf.js модель?

#javascript #bookshelf.js #knex.js

#javascript #bookshelf.js #knex.js

Вопрос:

У меня есть следующие таблицы:

  • books
  • book_reviews
  • users

Вот модели, которые соответствуют указанным таблицам:

 const BookReview = require('./BookReview').model;
const User = require('./User').model;

module.exports.model = bookshelf.Model.extend({
  tableName: 'books',

  user: function() {
    return this.hasOne(User, 'user_id');
  },

  reviews: function() {
    return this.hasMany(BookReview);
  }
});

module.exports.model = bookshelf.Model.extend({
  tableName: 'book_reviews',

  user: function() {
    // Prevent circular dependency.
    const User = require('./User').model;
    return this.belongsTo(User, 'user_id');
  },
});

module.exports.model = bookshelf.Model.extend({
  tableName: 'users',

  reviews: function() {
    return this.belongsToMany(BookReview, 'user_id');
  }
});
  

Я ищу книгу и пытаюсь получить все отзывы, которые у нее есть (и все пользователи, которые написали эти отзывы, прикреплены к отзывам, которые возвращаются), что в настоящее время выполняется со следующим утверждением:

 return Book.forge({
    id: req.params.id,
    type: req.params.type
  }).fetch({withRelated: ['reviews', 'reviews.user'], require: true}).then(function(book) {
    console.log(book.toJSON());
    return book;
  }).catch(function(err) {
    throw new Error(err.message);
  });
  

};

И вывод book.toJSON() сверху выглядит так:

Вывод из book.toJSON() сверху:

 { id: 1,
  type: 'novel',
  slug: 'catcher-in-the-rye',
  user_id: 1,
  name: 'Catcher in the Rye',
  created_at: Tue Oct 04 2016 22:35:42 GMT-0700 (PDT),
  updated_at: Tue Oct 04 2016 22:35:42 GMT-0700 (PDT),
  reviews: 
   [ { id: 14,
       user_id: 2,
       book_id: 1,
       rating: 3,
       review: 'Test',
       created_at: Wed Oct 05 2016 20:47:34 GMT-0700 (PDT),
       updated_at: Wed Oct 05 2016 20:47:34 GMT-0700 (PDT),
       user: [Object] } ] }
  

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

Я пытался добавить что-то подобное в User модель, но у меня не получилось сделать это правильно.

 numReviews: function(userId) {
        return new BookReview.query(function(qb){
            qb.where("user_id",userId);
            qb.count();
        }).fetch();
  },
  

Ответ №1:

Если вы хотите добавить метод к каждому экземпляру User модели, вы можете перезаписать constructor функцию следующим образом

 var User=bookshelf.Model.extend({
  tableName: 'users',
  constructor:function(){
    bookshelf.Model.apply(this, arguments);

    this.numReviews=function(){
      var thisUser=this;
      return new BookReview.query(function(qb){
        qb.where("user_id",thisUser.attributes.userId);
        qb.count();
        }).fetch();
    }
  }
});
  

Но я считаю, что этот подход будет работать плохо, поэтому, возможно, вам следует попробовать другой вариант. К сожалению, я не так часто использовал библиотеку bookshelf, поэтому у меня действительно нет никаких советов о более эффективном способе выполнения задачи.

В любом случае, надеюсь, это вам поможет.

Ответ №2:

После вашей строки console.log(book.toJSON()); вы можете получить доступ к количеству отзывов для книги, используя параметр length .

 console.log(book.reviews.length);
  

Потому что is array — это рецензии на книги, обозначаемые JSON как [...]

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

1. Мне нужно общее количество книг, которые есть у каждого пользователя для каждой книги. Это просто дало бы мне количество книг в коллекции.

2. @bob_cobb, я не понимаю «подсчет количества книг, которые у каждого пользователя есть для каждой книги»