В чем разница между dataloader и lodash.memoize? - PullRequest
0 голосов
/ 26 мая 2019

Я сделал демонстрацию, использует lodash.memoize для решения вопроса N + 1.

Вот мой запрос: 10 сообщений принадлежит 1 пользователю. И на стороне клиента GraphQL запрос выглядит так:

query {
  posts{
    postId
    postTitle
    postAuthor{
      userId
      userNme
      userEmail
    }
  }
}

Если не использовать dataloader или какую-либо функцию напоминания, он отправит 11 (10 + 1) запросов в базу данных. 1 временный запрос для posts, 10 временных запросов для пользователя каждого сообщения.

constructor() {
    super();
    this.userLoader = this.createLoader(this.findByIds.bind(this));
    this.userLoaderLodash = _.memoize(this.findByIds.bind(this));
  }

  public async findByIds(ids: string[]) {
    return this.db('users').whereIn('user_id', ids);
  }

  public async findById(id: string) {
    this.ids.push(id);
    // return new Promise((resolve, reject) => {
    // process.nextTick(() => {
    return this.userLoaderLodash(this.ids).then((users: any[]) => {
      // resolve(_.first(users));
      return _.first(users);
    });
    // });
    // }).then((user) => {
    // this.ids = [];
    // return user;
    // });

    // return this.userLoader.load(id);
  }

this.userLoader - это dataloader, this.userLoaderLodash реализуется lodash.memoize.

Вот журналы отладки базы данных:

{ method: 'raw',
  sql: '\n      SELECT * FROM posts;\n    ',
  bindings: [],
  options: {},
  __knexQueryUid: '046167c1-35d7-427f-8f3d-d4ac203670a6' }
{ method: 'select',
  options: {},
  timeout: false,
  cancelOnTimeout: false,
  bindings: [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
  __knexQueryUid: '450f19b7-3841-4c08-81f0-ca740f3abcf9',
  sql: 'select * from "users" where "user_id" in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' }

Как вы можете видеть, способ использования lodash.memoize также может решить проблему с запросом N + 1. Не использовать process.nextTick, кажется, не влияет на результаты.

...