1

i have web app pos the array filter search in client side in browser not in the server first i download all products as array and work on it and its working so good with number of products under 20k since a while the array of the products get the number of 50k

and my results array like this ..

   [
      {
        "id": 1,
        "name": "Product 1",
        "number": "1",
        "available_on_pos": 1,
        "pos_quick_lunch": 1,
        "product_category_id": 1,
        "discount_value": 10,
        "smallest_unit_id": 1,
        "smallest_unit_barcode": null,
        "smallest_unit_selling_price": 10,
        "smallest_unit_selling_price_above": null,
        "smallest_unit_selling_price_above_price": null,
        "tax_value": 16,
        "get_smallest_unit_id": {
          "id": 1,
          "name": "Unit"
        },
        "get_price_list_lines": []
      },
      {
        "id": 13,
        "name": "Product 2",
        "number": "13",
        "available_on_pos": 1,
        "pos_quick_lunch": null,
        "product_category_id": 1,
        "discount_value": null,
        "smallest_unit_id": 1,
        "smallest_unit_barcode": "9501025172815",
        "smallest_unit_selling_price": 0.509,
        "smallest_unit_selling_price_above": null,
        "smallest_unit_selling_price_above_price": null,
        "tax_value": 16,
        "get_smallest_unit_id": {
          "id": 1,
          "name": "Unit"
        },
        "get_price_list_lines": []
      }
    ]

and this is the search method

var results = this.products.filter(obj => obj.smallest_unit_barcode != null && obj.smallest_unit_barcode.includes(value));
this.pos_quick_lunch = results;

as i say the the products array is 50k the search like have delay when i press barcode gun multiable time at same product search and this is long time in pos to wait .. is there any way thats i can make the search much easer and faster

softya
  • 229
  • 7
  • 22
  • Why is 1 second not good enough for 50.000 products? The real solution would be to call an API, and that might also take 1 second. – tauzN Sep 18 '21 at 15:01
  • its not 1 sec but its not medetly there is an delay and i want to make the search time faster – softya Sep 18 '21 at 15:08
  • Have you ever heard the phrase ["if all you have is a hammer, everything looks like a nail"](https://en.wiktionary.org/wiki/if_all_you_have_is_a_hammer,_everything_looks_like_a_nail)? It looks like you're stuck in a bottleneck trying to do everything in one program. In a real-world POS system, your question is a process called a PLU(PriceLookUp), and it is common sense to increase the number of process, service, and server hosts to divide roles when dealing with a large number of cases. – kunif Sep 18 '21 at 17:24

3 Answers3

2

is there any way thats i can make the search much easer and faster

var results = this.products.filter(obj => obj.smallest_unit_barcode != null && obj.smallest_unit_barcode.includes(value));

As long as we keep the focus on this part of code and don't start discussions about general design ideas, I see a these options...

Cache the undefined case

Your could create a list of products with smalles_unit_barcode != null or undefined and keep it. This should give you a small improvement.

// do this only when products collection changes
const this.cachedProductsWithBarcode = this.products.filter(p => !!p.smallest_unit_barcode);

// do this on every request / input
const results = this.cachedProductsWithBarcode(p => p.smallest_unit_barcode.includes(value));

Do you need partial matches?

If you get the full article number / gtin, there's no need to do a partial search and you could use a dictionary lookup instead.

// only when products collection changes
const dict = this.products.reduce((prev, cur) => (prev[cur.smalles_unit_barcode] = cur, prev), {});

// for each request
return dict[value];

(If you get the full barcode most of the time but some times just a part of it, you could think about doing a lookup first and continue with a search if you have no match.)

Delay user input / Cache

If you search needle comes from a user input, where users can type the barcode and you do this search on every keystroke this search will block the UI making the app unusable. Delaying the user input (= do the search only if we get no more key strokes for e.g. 500ms) could improve the user experience.

In addition you could cache results

// User input "123"
// const firstResult = products.find(...)

// User input "1234"
// ... must be in firstResult, so let' search there
return firstResult.find(...)

(This makes only sense if it's 'search while typing' and you need the invalidate the cache if needle allows more results than cached results list.)

Misc...

  • Use startsWith() instead of includes() if possible (expect about 10% improvement) - if you can't use ==
  • Limit the number of results. In many cases you need only ONE result, so use find() instead. You should never need more than ~10 results, so stop filtering when this is reached.
  • Separate search and lookup in your UI. From my experience some people are really fast typing article codes + ENTER - (= full code = dict lookup = fast) but sometimes they don't know the full code and want a to search (= partial code = slow). Separating these two use cases can be as simple as using an input field with two buttons ("ok", "search" and ENTER = "ok"). Or you use a flow like type in input => ENTER => lookup full code in dict => not found? => show "not found, here are some results..."
Christoph Lütjen
  • 5,403
  • 2
  • 24
  • 33
0

It doest clear if you are talking about client js or a node.js server.

if you are talking about js run on your browser I think a much better approach is to make the back end do the filtering. I do not think a client should gets such a mount of data.

if you dealing with a node.js server you should consider improve your database query and let it do the filtering and not query the whole data.

zordon
  • 186
  • 9
  • 1
    The "use the backend" approach has some major drawbacks for POS systems e.g. slow due to network latencies or network may not be available. In general there's no reason why a server should be able to do things faster than a client. – Christoph Lütjen Sep 18 '21 at 15:07
  • 1
    another problem with filtering large scale data on the client is that filtering is a sync action.. meaning your main thread will freeze until the filtering will done – zordon Sep 18 '21 at 15:08
  • its not in the server side its on browser side in the front end i download all the products in the array in js and search on it – softya Sep 18 '21 at 15:10
  • 1
    there is a great reason why it should be much faster on a server. Its done on a much faster machine and not on relative slow home computer – zordon Sep 18 '21 at 15:13
  • 1
    @ChristophLütjen _"In general there's no reason why a server should be able to do things faster than a client."_ Wouldn't raw computation power be the main reason? Client could be on a ten year old mid-level machine. That plus querying from a DB with filter and sort defined in the query should (generally) be faster than doing it in code, no? – Alexander Nied Sep 18 '21 at 15:15
  • you may consider using web worker to do so if you have to do it on the client.https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers it will prevent from freezing the main thread by open a new thread – zordon Sep 18 '21 at 15:17
  • in pos system you cant do search in server side because the cashier will throw like 3 query per second you cant do that to server everytime they gun it will destroy the server imagine thats supermaker everytime they scan barcode it gone to the database thats so bad for the server – softya Sep 18 '21 at 15:19
  • If it runs slow on your computer imagine in a poorly maintained terminal. I agree with @zordon that filtering should be done from server-side. In fact, 3 queries per second is nothing for an API. Even there should be almost no latency if it's an intranet. In addition, API's can cache the query so no need to even hit the DB – Luciano Sep 18 '21 at 15:51
  • @AlexanderNied - we're talking about POS, where you typically have full control what hardware you use. IF you buy slow clients and a fast server you're right - the server will be faster. IF you need the features from an SQL server I'd do this on a server too - but the given use case may be a simple price lookup (equals, not includes) where a dictionary should be faster than every server roundtrip. – Christoph Lütjen Sep 18 '21 at 18:10
  • @zordon "Its done on a much faster machine and not on relative slow home computer" - true, but is "buy faster hardware / move it to faster hardware (server)" the best answer to "can I optimize this code for performance"? – Christoph Lütjen Sep 18 '21 at 18:15
-1

Product catalog search is generally done from the backend server side (especially since your dataset of products is so large and not just a few). You would need to implement a search field and button that calls an API. Also the results should be paginated, meaning you do not want to load all 50k products into the browser's memory or you will easily run into issues (especially in mobile devices) with app cache.

cantero
  • 34
  • 3