1

I'm returning results from a firebase query. The result is an array of objects with different properties. It's for a car app that I'm making. Each object look like this

{
   make: "make",
   model: "model",
   year: "year",
   gas: "petrol",
   mileage: "mileage",
   images: {
       image1: "url",
       image2: "url"
   }
}

I need to allow the users to be able to refine these results and I'm trying to come up with a robust solution

Problem: I need users to be able to refine results of a firebase query. The user will select different options for their refined search and so I need my function to be able to handle this

Where I'm up to

//Heres' how I planned to pass the refinement options
refinements = {
    make: 'value',
    model: 'value',
    year: 'value'
}

//currentResults is an array of objects with different properties

const refineResults = (currentResults, refinements) => {

    newResults = [];

    for (int i = 0; i < currentResults.count; i++ ){

        let currentResult = currentResult[i];

        for(int i = 0; i < refinements.count; i++){

        }
    }
}

I know I'm not very far into this function but I'm not even sure if I'm approaching this the right way. I'm unsure of how to access the property value via a for loop, as refinement.[I] doesn't make sense to compare

I basically want to loop through my current results and if all the values I have in my refinements object are equal, then I want to add this result to my new result array.

Thanks for any input

Icepickle
  • 12,689
  • 3
  • 34
  • 48
juicy89
  • 448
  • 5
  • 14
  • 1
    Can't [tag:firebase] take queries? Why would you handle the "refinements"? – Icepickle Mar 05 '18 at 15:40
  • Can you show us the `currentResults` data? You say it's an arrow with different properties... Sounds like it is an object. And if you are trying to loop through an object, you may have issues. – Stretch0 Mar 05 '18 at 15:40
  • 1
    Based off of my understanding, you're probably going to want to look into using `filter`. [There's an example using JSON on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) – vapurrmaid Mar 05 '18 at 15:41
  • Yes, firebase can accept queries, however I'm already preforming a firebase query to get the initial results. I also want to hold the old and new results so my users can chose to refine results based on different values @Stretch0 Yes the currentResults data is an array of objects exactly like the object at the start of my post. I'm returning about 100 of these objects in an array. Thanks – juicy89 Mar 05 '18 at 15:44
  • @Icepickle: Most likely OP is looking to filter on multiple properties. Firebase Database queries can only order/filter on a single property. In many cases it is possible to combine the values you want to filter on into a single (synthetic) property. For an example of this and other approaches, see my answer here: http://stackoverflow.com/questions/26700924/query-based-on-multiple-where-clauses-in-firebase. But if the filtering can't be done in a query, doing it in code can be the only remaining option. Of course: paying attention to bandwidth usage is key in that case. – Frank van Puffelen Mar 05 '18 at 15:48
  • @FrankvanPuffelen That's exactly right, there's actually more properties of each object than I've specified which makes for a lot of different possibilities. would the method of creating a single (synthetic) property still be viable in this case? – juicy89 Mar 05 '18 at 15:54

3 Answers3

2

Something like this will do the trick:

refinements = {
    make: 'Toyota',
    model: 'RAV4',
    year: '2010'
}

var currentResults = [
  { make: 'Toyota', model: 'Matrix', year: '2012' },
  { make: 'Toyota', model: 'RAV4', year: '2010' },
  { make: 'Chevrolet', model: 'Matiz', year: '2000' }
];

//currentResults is an array of objects with different properties

const refineResults = (currentResults, refinements) => {
    return currentResults.filter((car) => {
        /*var result = true;
        Object.keys(refinements).forEach(refinement => {
            if (car[refinement] !== refinements[refinement]) result = false;
        });
        return result;*/
        return !Object.keys(refinements).some(refinement => car[refinement] !== refinements[refinement]);

    });
}

console.log(refineResults(currentResults, refinements));

Key concepts used:

  • The code uses Array.filter to filter the current results down to only the ones matching the refinements.
  • The code uses Object.keys to determine just the keys (make, model and year) of the refinements, so that it can loop over them with Array.some (or the commented out Array.forEach).
  • *
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Just a nitpick: You mean `Array.prototype.filter` and same for `forEach`. – YoTengoUnLCD Mar 05 '18 at 15:59
  • Thanks for the detailed response @FrankvanPuffelen This looks to be exactly what I needed. I don't fully understand Object.keys and Array.some but will look into it straight away So I fully understand what's happening. Cheers – juicy89 Mar 05 '18 at 16:06
1

I'm not sure exactly how you expect the refinements object to work, but I've assumed that you need every property in each result to equal their corresponding property in each result. In which case the refineResults function below will help.

// helper func, returns true only if all props on `refinements` match their counterparts on `result`
function matchesAll(refinements, result) {
  for (const key in refinements) {
    if (refinements[key] !== result[key]) {
      return false;
    }
  }
  return true;
}

// returns filtered list of results
function refineResults(currentResults, refinements) {
  return currentResults.filter(result => matchesAll(refinements, result));
}
Aron
  • 8,696
  • 6
  • 33
  • 59
  • 1
    Thanks for replying Aron. This function looks great and a good alternative to the other solution. Will be looking into both answers – juicy89 Mar 05 '18 at 16:13
0

Using filter, the requirement given can be achieved and the function can be passed with more filtering business logics as arguments like greater than, less than and more. Give it a try.

Below is the simple code achieving the same.

var results = [
  {name:"john",age:15,price:400},
  {name:"joe",age:25,price:450},
  {name:"johnson",age:35,price:500}
];
var refine = {name:"john",age:15};

var result = results.filter(function(val){
 return val.name === refine.name && val.age == refine.age;
});

console.log(result);
Prashanth KR
  • 294
  • 2
  • 8