Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fuse.js : retrieve records which exactly match a multiple word search

Using Fuse.js I'm trying to make a "multiple word" search in a JS object to get the records which contain exactly each word looked for.

My data structure is the following (from fuse.js):

[{
    title: "The Lost Symbol",
    author: {
      firstName: "Dan",
      lastName: "Brown"
    }
 }, ...]

My issue is that my setup works for a one word search (Brown for example) but not for more (Dan Brown or Dan Brown Vinci).

Fuse options:

{
    shouldSort: true,
    matchAllTokens: true,
    findAllMatches: true,
    includeScore: true,
    threshold: 0,
    location: 0,
    distance: 100,
    maxPatternLength: 32,
    minMatchCharLength: 1,
    keys: [
        "title",
        "author.firstName",
        "author.lastName"
    ]
}

new Vue({
    el: "#app",
    data: {
        Fuse: null,
        searchText: '',
        result : [],
        fuseOptions: {
            shouldSort: true,
            matchAllTokens: true,
            findAllMatches: true,
            includeScore: true,
            threshold: 0,
            location: 0,
            distance: 100,
            maxPatternLength: 32,
            minMatchCharLength: 1,
            keys: [
                "title",
                "author.firstName",
                "author.lastName"
            ]
        },
        list: [{
                title: "Old Man's War",
                author: {
                    firstName: "John",
                    lastName: "Scalzi"
                }
            },
            {
                title: "The Lock Artist",
                author: {
                    firstName: "Steve",
                    lastName: "Hamilton"
                }
            },
            {
                title: "HTML5",
                author: {
                    firstName: "Remy",
                    lastName: "Sharp"
                }
            },
            {
                title: "Right Ho Jeeves",
                author: {
                    firstName: "P.D",
                    lastName: "Woodhouse"
                }
            },
            {
                title: "The Code of the Wooster",
                author: {
                    firstName: "P.D",
                    lastName: "Woodhouse"
                }
            },
            {
                title: "Thank You Jeeves",
                author: {
                    firstName: "P.D",
                    lastName: "Woodhouse"
                }
            },
            {
                title: "The DaVinci Code",
                author: {
                    firstName: "Dan",
                    lastName: "Brown"
                }
            },
            {
                title: "Angels & Demons",
                author: {
                    firstName: "Dan",
                    lastName: "Brown"
                }
            },
            {
                title: "The Silmarillion",
                author: {
                    firstName: "J.R.R",
                    lastName: "Tolkien"
                }
            },
            {
                title: "Syrup",
                author: {
                    firstName: "Max",
                    lastName: "Barry"
                }
            },
            {
                title: "The Lost Symbol",
                author: {
                    firstName: "Dan",
                    lastName: "Brown"
                }
            },
            {
                title: "The Book of Lies",
                author: {
                    firstName: "Brad",
                    lastName: "Meltzer"
                }
            },
            {
                title: "Lamb",
                author: {
                    firstName: "Christopher",
                    lastName: "Moore"
                }
            },
            {
                title: "Fool",
                author: {
                    firstName: "Christopher",
                    lastName: "Moore"
                }
            },
            {
                title: "Incompetence",
                author: {
                    firstName: "Rob",
                    lastName: "Grant"
                }
            },
            {
                title: "Fat",
                author: {
                    firstName: "Rob",
                    lastName: "Grant"
                }
            },
            {
                title: "Colony",
                author: {
                    firstName: "Rob",
                    lastName: "Grant"
                }
            },
            {
                title: "Backwards, Red Dwarf",
                author: {
                    firstName: "Rob",
                    lastName: "Grant"
                }
            },
            {
                title: "The Grand Design",
                author: {
                    firstName: "Stephen",
                    lastName: "Hawking"
                }
            },
            {
                title: "The Book of Samson",
                author: {
                    firstName: "David",
                    lastName: "Maine"
                }
            },
            {
                title: "The Preservationist",
                author: {
                    firstName: "David",
                    lastName: "Maine"
                }
            },
            {
                title: "Fallen",
                author: {
                    firstName: "David",
                    lastName: "Maine"
                }
            },
            {
                title: "Monster 1959",
                author: {
                    firstName: "David",
                    lastName: "Maine"
                }
            }
        ]

    },
    methods: {
        fuseSearch: function() {
            let self = this;
            
            this.result = this.Fuse.search(self.searchText)
        }
    },

    mounted() {
    		let self = this
        this.Fuse = new window.Fuse(self.list, self.fuseOptions);
        

    }
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

table {
  width: 100%;
  margin-top:20px
}

table th{
  font-weight:bold
}
table td{
  padding-top:5px
}

input{
  height:30px;
  width:200px;
  font-size:14px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/3.2.1/fuse.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>

<div id="app">
  <input type="text" v-model="searchText" @keyup="fuseSearch()" placeholder="search for text">
  
  
  <div v-if="result.length == 0" style="margin-top:10px">No matching results, here is the full list</div>
  <div v-else style="margin-top:10px">{{result.length}} records found</div>
  
  
  
  <table>
    <tr>
      <th>Title</th>
      <th>FistName</th>
      <th>LastName</th>
      <th>Score</th>
    </tr>
    
    <tr v-if="result.length >0" v-for="data in result" >
      <td>{{data.item.title}}</td>
      <td>{{data.item.author.firstName}}</td>
      <td>{{data.item.author.lastName}}</td>
      <td>{{Math.round(data.score*100,2)/100}}</td>
    </tr>
    
    <tr v-if="result.length == 0" v-for="data in list">
    
      <td>{{data.title}}</td>
      <td>{{data.author.firstName}}</td>
      <td>{{data.author.lastName}}</td>
      <td></td>
    </tr>
  </table>

</div>
like image 798
Sebastien D Avatar asked Jul 05 '18 09:07

Sebastien D


1 Answers

Unfortunately, fuse.js does not look into all fields, rather one matching field. I solved this problem by putting all the fields into one field with array of strings.

Example:

[{
    title: "The Lost Symbol",
    author: {
      firstName: "Dan",
      lastName: "Brown"
    },
    keywords: ["The Lost Symbol", "Dan", "Brown"] //values of title, firstname & lastname
 }, ...]

And just specify keywords Fuse option's keys field

{
    shouldSort: true,
    matchAllTokens: true,
    findAllMatches: true,
    includeScore: true,
    threshold: 0,
    location: 0,
    distance: 100,
    maxPatternLength: 32,
    minMatchCharLength: 1,
    keys: ["keywords"]  //just put keywords alone
}

This worked for me. Hope it works for you too.

like image 114
Kumar Avatar answered Oct 16 '22 10:10

Kumar