Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Client-side full-text search on array of objects

I have the following example JavaScript array of objects and need to enable users to search on it using words/phrases, returning the objects:

var items = [];
var obj = {
    index: 1,
    content: "This is a sample text to search."
};
items.push(obj);
obj = {
    index: 2,
    content: "Here's another sample text to search."
};
items.push(obj);

It's probably efficient to use jQuery's $.grep to perform the search, such as this for a single word:

var keyword = "Here";
var results = $.grep(items, function (e) { 
    return e.content.indexOf(keyword) != -1; 
});

However, how do you search for a phrase in the content field of the objects? For example, searching for the phrase another text won't work using indexOf, because the two words aren't next to each other. What's an efficient way to perform this search in jQuery?

like image 207
Alex Avatar asked Jun 17 '15 12:06

Alex


2 Answers

You can use vanilla JS if you're stuck. It does use filter and every which won't work in older browsers, but there are polyfills available.

var items = [];

var obj = {
  index: 1,
  content: "This is a sample text to search."
};

items.push(obj);

obj = {
  index: 2,
  content: "Here's another sample text to search."
};

items.push(obj);

function find(items, text) {
  text = text.split(' ');
  return items.filter(item => {
    return text.every(el => {
      return item.content.includes(el);
    });
  });
}

console.log(find(items, 'text')) // both objects
console.log(find(items, 'another')) // object 2
console.log(find(items, 'another text')) // object 2
console.log(find(items, 'is text')) // object 1

(Edit: updated to use includes, and a slightly shorter arrow function syntax).

like image 114
Andy Avatar answered Nov 11 '22 18:11

Andy


if you use query-js you can do this like so

var words = phrase.split(' ');
items.where(function(e){
           return words.aggregate(function(state, w){ 
                    return state && e.content.indexOf(w) >= 0;
                  });
},true);

if it should just match at least one change the && to || and true to false

like image 42
Rune FS Avatar answered Nov 11 '22 19:11

Rune FS