Получить большой набор данных (~ 20000 предметов) из mongodb и отобразить их на угловом 7 Страница продуктов администратора - PullRequest
0 голосов
/ 23 марта 2019

Я пытаюсь получить ~ 20000 элементов из Mongodb и отобразить их на моей странице Angular 7 Project на странице продуктов администратора в таблице

Проблема в том, что веб-сайт занимает слишком много времени, а иногда ион падает

Есть ли способ получить их как 1000 элементов за другим, быстро получить их или разбить на страницы как 0-1000 элементов на странице 1 и 1000-2000 на странице 2?

Я искал его и не нашел здесь ни одного полезного ресурса или даже подобного вопроса.

Я обнаружил, что могу ограничить количество элементов в mongodb, используя этот код:

ITEMS_COLLECTION.find({}).limit(1000).toArray((err, allItems) => {
            items = allItems
        })

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

Это страница товара: src> Item.js

function getItems() {
    let items

    Server().then((server_data) => {
        server_data.ITEMS_COLLECTION.find({}).limit(1000).toArray((err, allItems) => {
            items = allItems
        })
    })

    /*eslint no-undef: 0*/
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(items)
        }, 4000)
    })
}

Это страница сервера: src> server.js

app.get('/activeProducts', (req, res) => {
    Item.getActiveItems()
        .then(active_items => {
            res.send(active_items);
        })
        .catch(err => {
            throw new CustomError('Could not get Active Items', err);
        });
});

Это Служба продуктов:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { LoginService } from './login.service';
import { Router } from '@angular/router';

import { MatDialog, MatDialogRef } from '@angular/material';

import { environment } from '../../environments/environment';

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json',
    Authorization: 'my-auth-token'
  })
};
@Injectable()
export class ProductsService {
  products = this.http.get(
    ` ${environment.link_url_with_backend}/activeProducts`
  );
  cached_products;

  constructor(
    private loginService: LoginService,
    private router: Router,
    private http: HttpClient,
    public dialogRef: MatDialog
  ) {
    this.products.subscribe(data => {
      console.log(data);
      this.cached_products = data;
    });
  }
}

ЭтоКомпонент продуктов:

export class ProductsComponent implements OnInit, DoCheck {
  constructor(private productService: ProductsService) {}

  products;

  ngOnInit() {
    this.products = this.productService.cached_products;
  }
}

Это HTML-код продуктов:

<div
  class="products-container wrapper"
>
  <app-product
    *ngFor="let product of products"
    [product]="product"
    style="width: 360px;"
  ></app-product>
</div>

1 Ответ

1 голос
/ 25 марта 2019

Прежде всего, в Backend вам нужно получить первые 100, например:

function getFirst100Items() {
    let items

    ITEMS_COLLECTION
        .find({})
        .limit(100)
        .sort({id: 1})
        .toArray( (err, allItems) => {
            items = allItems
        })


    return new Promise(resolve => {
        setTimeout(() => {
            resolve(items)
        }, 2000)
    })
}

Затем вы можете добавить функцию load more, например:

function getMore100Items(loadedItems) {
    let items


    server_data.ITEMS_COLLECTION
        .find({ id: { $gte: loadedItems } })
        .limit(100)
        .sort({id: 1})
        .toArray( (err, allItems) => {
            items = allItems
        })

    return new Promise(resolve => {
        setTimeout(() => {
            resolve(items)
        }, 2000)
    })
}
function getItemsCount() {
    let itemsCounts


    server_data.ITEMS_COLLECTION.countDocuments()
        .then( (counts) => {
            itemsCounts = counts
        })

    return new Promise(resolve => {
        setTimeout(() => {
            resolve({itemsCounts})
        }, 1000)
    })
}

Тогда вы задаетеэкспресс-маршруты

app.get('/first/100products', (req, res) => {
    Item.getFirst100Items()
        .then(items => {
            res.send(items);
        })
        .catch(err => {
            throw new CustomError('Could not get Items', err);
        });
});

app.post('/loadmore/products', (req, res) => {
    loaded_items = req.body.loadedItems
    res.send({loaded_items})
});

app.get('/loadmore/products', (req, res) => {
    setTimeout(() => {
        Item.getMore100Items(loaded_items)
            .then(items => {
                res.send(items);
            })
            .catch(err => {
                throw new CustomError('Could not get Items', err);
            });

    }, 2000);

});

Second In Angular 7

Родительский компонент

loadedItems = 0;

  @ViewChild(AdminTableComponent) adminTable;

  constructor(public dialog: MatDialog, private http: HttpClient) {
    this.http
      .get(` ${environment.link_url_with_backend}/first/100products`)
      .subscribe((data: {}[]) => {
        this.products_data = data;
        this.dataSource = new MatTableDataSource(this.products_data);
      });
  }
  ngOnInit() {}

  loadMore() {
    this.http
      .get(` ${environment.link_url_with_backend}/products/length`)
      .subscribe((itemsCount: any) => {
        if (this.loadedItems < itemsCount.itemsCounts - 100) {
          this.adminTable.isLoad = true;
          this.loadedItems += 100;

          this.http
            .post(
              `${environment.link_url_with_backend}/loadmore/products`,
              JSON.stringify({ loadedItems: this.loadedItems }),
              httpOptions
            )
            .subscribe(data => {
              console.log(data);
            });

          this.http
            .get(` ${environment.link_url_with_backend}/loadmore/products`)
            .subscribe((items: {}[]) => {
              items.map(product => {
                this.products_data.push(product);
                this.dataSource = new MatTableDataSource(this.products_data);
                this.adminTable.isLoad = false;
                this.adminTable.dataSource.sort = this.adminTable.sort;
                this.adminTable.dataSource.paginator = this.adminTable.paginator;
                return;
              });
            });
        } else {
          this.adminTable.isLoad = false;
          this.adminTable.isLoadMore = false;
          alert('No More Products to Get');
          return;
        }
      });
  }

ChildComponent

  loadMoreItems() {
    this.loadMore.emit('loadMore');
  }
  @Input() dataSource;
  @Input() displayedColumns;
  @Input() dialogComponent;
  @Output() loadMore = new EventEmitter();

  isLoad = false;
  isLoadMore = false;


И вы можете продолжить отсюда

Надеюсь, это поможет!

Note: Все это только пример, так что не принимайте это точно

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