2

I have some data in the database used for a SEARCH BAR. In this table the field is called searchPeople (all lowercase) and contains data like:

 Name##CityName
 john##rome
 romeu##napoli
 romeu2##milan

So the user types on the SEARCH BAR some thing Rome, people that contain Rome in either their name or city. The search works well but I would like to "PRIORITIZE" the exact match String on top of the array. currently the data comes in random by the database order

 {
    name: 'John',
    city: 'Rome'
  }

Should be on top because the city matches === the string given by the user. THis can either be the name or city, I just gave an example using city match

const people = [{
    name: 'Romeu',
    city: 'Napoli'
  },
   {
    name: 'John',
    city: 'Rome' // this object should be first because there is a matching result
  },
  {
    name: 'Romeu2',
    city: 'Milan'
  }
];

console.log(people);

   // How can I sort people array with most relevant results on top?

Is there a way to sort my array to put the more correct search results on top?

7
  • you forgot the .sort part of your code Commented Sep 16, 2022 at 8:47
  • @JaromandaX I tried to develop but I didn't understand how to implement. The exact part I am missing is the sort Commented Sep 16, 2022 at 8:48
  • 1
    here you go Commented Sep 16, 2022 at 8:49
  • sort can accept a function that accepts two elements from your array. This comparator then returns the relationship between the elements (a equals b, a < b, a > b). You only need to implement this comparator according to your requirements. Commented Sep 16, 2022 at 8:50
  • I assume you also want to filter out results that don't match the query at all? Commented Sep 16, 2022 at 8:50

4 Answers 4

1

You can do it like this:

  • sort - to sort original array
  • includes - to check if user input is exact match of either name or city property.

const data = [
  { name: 'Romeu', city: 'Napoli' },
  { name: 'John',  city: 'Rome' },
  { name: 'Romeu2', city: 'Milan' },
];

const result = data.sort((a, b) => [a.name, a.city].includes('Rome') ? -1 : 0);
console.log('Result: ', result);

Sign up to request clarification or add additional context in comments.

Comments

1
people.sort((a, b) => {
if(a.city.toLowerCase() === '*user-input*'.toLowerCase() || a.name.toLowerCase() === '*user-input*'.toLowerCase()) {
  return -1;
}
return 0;
})

you can try this.

Comments

0

What you're speaking about is called 'relevance'. And you need somehow calculate it. And first you need to define it somehow. What is considered as more relevant in this particular search? Is name match more relevant than city match? Strict match is more relevant than partial match, that's clear.

So, strict match contributes to relevance value more that a partial match. For instance, strict match on field 'city' might give a value of 10 to a relevance score. While partial match on the beginning of a name can give value of 5. And maybe some variations of partial match contribute more than others.

For instance, search term me might contribute 1 for name Romeu and contribute 2 for city Rome (because matching the end might be defined as a more relevant than matching some center part of the word). And so on.

3 Comments

That's a deep rabbit hole to go into. Before they know it, they will have built Sphinx, but in javascript :)
I just want to check if there are exact match in either city or name and if it's a match just put on top of the array, if not just don't do anything. Doesn't seem to be very complex
@asfafafags what about corner cases, like one record has two exact matches and another one has one full match? What about cases with few words in search criteria and in name / city? General approach for this is not a trivial thing. And you already got an answer about simplistic approach
0

Does this do what you want?

Function reorder accepts the array to sort, the field to sort on, and the query string. It constructs a regular expression that looks for the exact word, delineated by word boundaries; this is then used to sort the array on the basis of matches.

If you want to sort on a second field (eg 'name'), then you could run this function again on that field.

const people = [{
    name: 'Romeu',
    city: 'Napoli'
  }, {
    name: 'John',
    city: 'Rome'
  }, {
    name: 'Romeu2',
    city: 'Milan'
  }]

const reorder = ({ arr, field, q }) => {
    let r = new RegExp(`\\b${q}\\b`, 'u')
    
    return arr.sort(({ [field]: aField }, { [field]: bField }) => {
        if(r.test(aField) && !r.test(bField)) return -1
        if(!r.test(aField) && r.test(bField)) return 1
        return 0
    })
}

console.log(reorder({ arr: people, field: 'city', q: 'Rome' }))

2 Comments

Why would you go to the expense of a RegEx when you are looking for an exact match?
Thanks for your input, Mike. I interpreted the requirement to be that the exact match could be contained within the field, delineated by word boundaries. So both "London" and "Greater London" would be prioritised and "Londony" would be left untouched.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.