Managing numerous incoming inquiry requests

My API serves JSON data. Currently, accessing api/weapons will provide all available weapons, while api/weapons/weaponName gives information about a specific weapon. My goal is to filter results using parameters like

api/weapons?type=sword&rarity=5
. I have managed to filter by type and rarity individually with api/weapons?type=sword and api/weapons?rarity=5 but not together.

This is my current approach:

  let filtered = [];
  if (query.type) {
    filtered = filtered.concat((await weapons).filter(w => formatName(w.weaponType) === formatName(query.type)));
  }
  if (query.rarity) {
    filtered = filtered.concat((await weapons).filter(w => w.rarity == query.rarity));
  }
  if (!filtered.length) filtered = [await weapons];
  res.status(HttpStatusCodes.ACCEPTED).send(filtered);

formatName is simply a function that converts a string to lowercase, trims it, and removes spaces.

If we consider the example

api/weapons?type=sword&rarity=5
, the current behavior is:

  1. Retrieve all weapons of type "sword"
  2. Retrieve all weapons with rarity "5"
  3. Combine both sets of results, showing all swords regardless of rarity and all weapons with rarity 5 regardless of type.

I aim to only display weapons that match both the specified rarity AND type criteria, such as swords with a rarity of 5. What would be the most efficient way to achieve this filtering?

Answer №1

To improve efficiency, it is recommended to fetch "weapons" once and apply filters separately without combining the results:

let filtered = [ ...(await weapons) ];

if (query.type) {
  filtered = filtered.filter(w => formatName(w.weaponType) === formatName(query.type));
}

if (query.rarity) {
  filtered = filtered.filter(w => w.rarity == query.rarity);
}

res.status(HttpStatusCodes.ACCEPTED).send(filtered);

Answer №2

Your current approach involves testing if one constraint OR another matches, but what you actually need to do is perform an AND operation. This means that the test should be conducted in a single pass of the filter method.

To achieve this, I suggest making some slight modifications to your code so that all constraints are compared. You can even further adjust the logic to include a logical operator for checking whether the rarity is greater than or equal to (>=) or less than or equal to (<=) a certain number, for instance.

const weapons = [{
    type: 'sword',
    name: 'swift blade of zek',
    rarity: 5
  },
  {
    type: 'mace',
    name: 'hammer of kromzek kings',
    rarity: 1
  },
  {
    type: 'sword',
    name: 'split blade of thunder',
    rarity: 2
  },
  {
    type: 'sword',
    name: 'blade of carnage',
    rarity: 5
  },
]

const getWeapons = (query = {}) => {
  let filtered = [];
  let constraints = [];

  // Instead of hardcoding, we could dynamically build this object
  // However, for demonstration purposes, I am following your current approach
  if (query.hasOwnProperty('type')) {
    constraints.push({
      name: 'type',
      value: query.type
    })
  }

  if (query.hasOwnProperty('rarity')) {
    constraints.push({
      name: 'rarity',
      value: query.rarity
    })
  }

  // Compare all the conditions and only return weapons that satisfy all specified constraints
  filtered = weapons.filter(w => {
    let matches = 0
    constraints.forEach(c => {
      if (w[c.name] === c.value) {
        matches += 1
      }
    })
    // Return only complete matches
    return matches === constraints.length
  });

  return filtered
}

console.log(getWeapons({
  type: 'sword',
  rarity: 5
}))

Answer №3

To implement filtering functionality, create an object containing functions that specify the evaluation criteria for each filter you want to apply.

const filters = {
  type: (weapon, type) => formatName(weapon.weaponType) === formatName(type),
  rarity: (weapon, rarity) => weapon.rarity === rarity,
};

Next, iterate through the weapons using the filter method. Within this loop, go through the keys of the query object using the every method, which returns true only if all evaluations are met.

Within the every loop, select the corresponding filter function from the filters object based on the key in the query. Pass the weapon and query values to these functions and return the result.

This approach allows utilizing one, multiple, or no filters at all. Additionally, new filters can easily be added to the filters object.

const filteredWeapons = weapons.filter((weapon) =>
  Object.keys(query).every((filterKey) => {
    if (!(filterKey in filters)) {
      return false;
    }

    const filter = filters[filterKey]
    const value = query[filterKey]
    return filter(weapon, value);
  })
);

res.status(HttpStatusCodes.ACCEPTED).send(filteredWeapons);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Implement admin-on-rest framework within my current project

Currently, I am in the process of building an admin-tool website using Material UI. To handle asynchronous calls, I have integrated Redux Saga into my project for calling services. The Admin on Rest framework offers some beneficial components like the Data ...

To add an object to an array in Javascript, use the following format: [{...}, {...}]

Let's say we have a variable named var testVar = []; and we receive data via ajax in the following format: { "Country": "ALA Aland Islands", "CountryCode": "AX", "Slug": "ala-aland-islands", "Population": 100000, "Teenagers": 50000, "Mid ...

Arranging information extracted from an XML document following an ajax request

Here is a snippet of XML data sample to work with: <?xml version="1.0" encoding="ISO-8859-1"?> <CATALOG> <CD> <TITLE>Empire Burlesque</TITLE> <ARTIST>Bob Dylan</ARTIST> <COUNTRY>U ...

A guide to implementing SSR layout using Next-Auth

Currently, I am facing an issue in my project where the session is being automatically set to client-side. However, when I build the project, the page remains dynamic with the client-side session. If I remove the next-auth project, the page switches to SSR ...

I am looking to dynamically add values into a hash map

var markerList1={}; var markerList=[]; and incorporating iterator values from a single for loop function addSomething() // this function will run multiple times from a for loop { image ='../css/abc/'+image[iterator]+'.png&apos ...

Changing guid bytes into a string using JavaScript

Currently, I am receiving an arrayBuffer from a WebSocket connection and within that, I am able to obtain a range of byte arrays representing a Guid created in C#. I am wondering how I can convert these Guid bytes to a string in JavaScript? Guid: "FEF38A ...

Problem with sorting when using $in operator in MongoDB

I am looking to retrieve documents from a MongoDB collection where the IDs match those in an array: [ '5f80a44d0179262f7c2e6a42', '5f8c00762fae890e9c4d029c', '5f802cf8abac1116a46bf9d4' ] The problem arises when the docu ...

Troubleshooting npm audit error involving loadVirtual and ENOLOCK

➜ npm safety check npm ERR! code ENOLOCK npm ERR! safety check This operation requires an existing lockfile. npm ERR! safety check Please generate one using: npm i --package-lock-only npm ERR! safety check Original error: loadVirtual needs a preexistin ...

Dealing with a 404 error after accepting a slack modal submission using nodeJS and express

I'm struggling to retrieve the data from a Slack modal submission using nodeJS and express. Below is the Slack view that I can successfully open through an interactive component { view: { 'type': 'modal', 'title&ap ...

Discovering the magic of obtaining a random element in Vue.js

I have 3 captivating hero images along with their unique content, and I am looking to showcase them randomly to users each time they refresh the page! My challenge lies in efficiently loading these large hero images using jQuery. Currently, all three imag ...

Understanding the process of extracting triangle and vertex information from an STL file

Could someone share the method to extract vertices and triangles data from an STL format model in ThreeJS? ...

What is the best way to pass a prop into the <router-link>?

If I replace this {{ name }}, the result is "campaigns" Now, I want to use that in my link <router-link :to="'/' + '123' + '/' + item.id"> {{ item.name }}</router-link> I attempted to substitute '1 ...

Setting the ng-class attribute on an AngularJS accordion-heading element seems ineffective

I'm encountering an issue with my accordion setup. Some entries in the accordion require a heading that highlights when there is a problem that needs attention. I attempted to use an "accordion-heading" with a conditional "ng-class" for "has-error" (t ...

The speed at which Laravel loads local CSS and JS resources is notably sluggish

Experiencing slow loading times for local resources in my Laravel project has been a major issue. The files are unusually small and the cdn is much faster in comparison. Is there a way to resolve this problem? https://i.stack.imgur.com/y5gWF.jpg ...

Retrieve a specific line of code from a snippet of JavaScript

I am looking to extract a specific line of code from a script that I am receiving via ajax... The line in question is new Date(2010, 10 - 1, 31, 23, 59, 59) found within the following snippet: jQuery(function () { jQuery('#dealCountdown').count ...

Optimizing logical expressions in C++

Can I assume in C, C++, JavaScript, or any other modern language that if I have the following code snippet... bool funt1(void) {…} bool funt2(void) {…} if (funt1() && funt2()) {Some code} ...I am guaranteed that both functions will be called, ...

Triggering a hover effect by invoking a jQuery function when a href is clicked

Hey there, sorry if I'm a bit confused or misinterpreting things, but I'm still getting the hang of jQuery and javascript. I've created an online shop using PHP, and one essential element is a jQuery cart that needs to be displayed on every ...

Storing an array of dates in a Rails database by saving each date on a separate row within the table

I need to create a booking system that allows users to select multiple dates. To enable this functionality, I am utilizing the jQuery multiDatesPicker plugin: <%= form_for @showing, :html => { multipart: true } do |f| %> <%= f.text_field :d ...

Implementing Angular $resource to prepopulate a form with data

My goal is to enable CRUD operations so that when a user selects a specific item to edit, the form will automatically populate with the corresponding values for editing. Below is an excerpt of code from the 'storeView.html' file: <tr data-ng ...

Combine two arrays of objects while avoiding objects with duplicate ID properties

I have two arrays of objects that I need to merge, but I want to exclude any objects with duplicate IDs (I only want to keep the first object with each ID). One array is stored locally, and the other is retrieved from an API. const localUsers = [ { ...