Rxjs поиск в Angular

Я создал rxjs-поиск компании по найму, но получил отказ по следующей причине: — проблема с производительностью на большом наборе данных. -бухи

У меня вопрос, как я могу улучшить этот код в следующий раз, если у меня будет аналогичная задача?

Brands = Они должны быть заполнены из свойства бренда из коллекции продуктов.

Поиск должен соответствовать по названию, описанию и свойствам бренда.

  • Поиск не должен запускаться, пока не будет набрано минимум три символа.
  • Поиск должен запускаться не чаще одного раза в 400 миллисекунд.

При поиске «xxx» с выбранным брендом «xxx» и «В наличии» будут отображаться только товары, соответствующие всем трем фильтрам.

const stackoverflowFilter = (filter: ISearch) => {
  return (product: IProducts): boolean => {
    return ((
      (
        (product.name.toLowerCase().indexOf(filter.input.toLowerCase()) !== -1) ||
        product.description.toLowerCase().indexOf(filter.input.toLowerCase()) !== -1 ||
        product.brand.toLowerCase().indexOf(filter.input.toLowerCase()) !== -1) &&
      product.brand.toLowerCase().indexOf(filter.select.toLowerCase()) !== -1 &&
      (filter.radio === 'all' ? true : filter.radio === 'in-stock' ? product.quantity > 0 : product.quantity === 0)
    )
    )
  };
};

export interface ISearch { input: string; select: string; radio: string }



> public getStackoverflow(): Observable<Stackoverflow[]> {
>         return of([
>           {
>             id: "1",
>             name: "This is just test data",
>             price: "89.9",
>             description: "test data",
>             brand: "stackoverflow",
>             quantity: 4
>           }....])}



 this.stackoverflow$ = this.service.getStackoverflow();

    this.stackoverflow$.pipe(
      tap((prod) => {
        this.stackoverflow = prod;
        this.brands = this.stackoverflow.map(({ brand }) => brand).reduce((prev, cur) => {
          if (prev.indexOf(cur) < 0) prev.push(cur);
          return prev;
        }, []);
      }),
      concatMap(() =>
        this.search$.pipe(
          debounceTime(400),
          distinctUntilChanged(),
          switchMap((search: string) =>
            iif(() => search.length >= 3,
              this.stackoverflow$.pipe(
                map(stackoverflow=> stackoverflow.filter(stackoverflowFilter(this.filter))),
                distinctUntilChanged((curr, prev) => curr === prev),
              ),
              this.stackoverflow$.pipe(
                filter(() => search.length === 0),
              )
            )
          )
        ))
    ).subscribe(
      stackoverflow=> { this.stackoverflow= stackoverflow; },
      (err) => throwError(err)
    );

1 ответ
1

Если имеется 1 миллион наборов данных, и я ввожу первые три буквы, ему придется отфильтровать все 1 миллион значений (допустим, результат будет 200 совпадений). Когда я теперь добавляю четвертую букву, ей придется СНОВА фильтровать все 1 миллион значений, а не только 200 совпадений.

Таким образом, если абсолютно необходимо выполнить фильтрацию кода, вы можете реализовать своего рода эффект памяти.

Когда выполняется первая фильтрация (после первых трех букв), вы сохраняете поисковую фразу и результат фильтрации. Когда теперь добавляется четвертая буква, вы просто проверяете, остались ли первые три буквы такими же. Если да, то вы можете сократить свою фильтрацию, просто отфильтровав сокращенный список из предыдущей фильтрации.

Таким образом вы меняете время выполнения на потребление памяти (типичный компромисс).

Мой вопрос был бы в том, абсолютно ли необходимо выполнять фильтрацию в коде. Когда этот поиск следует применять в основном к большим наборам данных, я бы переместил фильтрацию на бэкэнд. Тогда у вас будет намного больше запросов к бэкэнду, но бэкэнд (если быть точным, база данных) мог бы обрабатывать такую ​​фильтрацию намного эффективнее.

Но как всегда, это зависит от обстоятельств. Для небольших наборов данных время приема-передачи (FE -> BE -> FE) для каждого поискового запроса поглотит весь прирост производительности, который вы получили благодаря более эффективной фильтрации. Но для больших наборов данных время приема-передачи будет меньше по сравнению с производительностью фильтрации (и потреблением памяти) на клиенте.

С наилучшими пожеланиями, Ян

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *