1.10.6 • Published 5 years ago

node-suggestive-search v1.10.6

Weekly downloads
17
License
MIT
Repository
github
Last release
5 years ago

Node suggestive search

Don't let spelling mistakes prevent your users from finding what they were looking for! This node module was built to help type-ahead and dropdown search boxes and also correct misspelled searches (did you mean?).

This module is compatible with:

Installation, tests

Module name on npm is "node-suggestive-search".

npm install node-suggestive-search --save   # Install the latest version in your project

Example of usage

https://node-suggestive-search.herokuapp.com

API

  • Setting options
  • Loading a database
  • Searching for items
  • Getting words suggestions
  • Getting items suggestions
  • Insert items
  • Remove items

Setting options

This module supports Redis, MongoDB and NeDB but you can use an in-memory volatile cache.

Configuration without database (in-memory):

var nss = require('node-suggestive-search').init();

Configuration without database with cache (in-memory):

var nss = require('node-suggestive-search').init({ cache: true });

Configuration using Redis:

var nss = require('node-suggestive-search').init(
			{
			dataBase: "redis", 
			redisDatabase: "redis://localhost:6379",
			cache: true
			});

Configuration using MongoDB:

var nss = require('node-suggestive-search').init(
			{
			dataBase: "mongodb", 
			mongoDatabase: "mongodb://127.0.0.1:27017/nodeSugestiveSearch",
			cache: true
			});

Configuration using NeDB with a datafile:

var nss = require('node-suggestive-search').init(
			{
			dataBase: "nedb", 
			neDbDataPath: "dataFolder",
			neDbInMemoryOnly: false,
			cache: true
			});

Configuration using NeDB without a datafile (in-memory):

var nss = require('node-suggestive-search').init(
			{
			dataBase: "nedb", 
			neDbDataPath: "",
			neDbInMemoryOnly: true,
			cache: false
			});

There is also an option to include stop-words:

var nss = require('node-suggestive-search').init(
			{
			stopWords: ["1033", "1046", ..., __dirname + "\\yourOwnStopWords.json"]
			});
			
//current built-in available stopwords dictionary
//1033 - en-us - English - United States
//1036 - fr-fr - French - France
//1040 - it-it - Italian - Italy
//1046 - pt-br - Portuguese - Brazil
//1048 - ro    - Romanian - Romania
//2057 - en-gb - English - Great Britain
//2070 - pt-pt - Portuguese - Portugal

The "cache" option enables an in-memory copy of the data structure boosting the performance. Turn off this option if you have more than one instance accessing the same database.

Loading a database

Build a dictionary composed by items and words that need to be searched.

Example of a JSON to be imported (Items.json):

[  
   {  
      "itemName":"WHISKY RED LABEL",
      "itemId":"1",
      "keywords":"FANCY" 
   },
   {  
      "itemName":"WHISKY BLACK LABEL",
      "itemId":"2",
      "keywords":"EXPENSIVE"
   },
   {  
      "itemName":"BLACK FOREST LABELY HAM L/S",
      "itemId":"3"
   },
   {  
      "itemName":"PESTO PARMESAN HAM",
      "itemId":"4"
   },
   {  
      "itemName":"DELI SWEET SLICE SMOKED HAM",
      "itemId":"5"
   }  
]

Load the JSON from file

//you can change the charset to match your file
nss.loadJson("Items.json", "utf8").then(data => {
	// response: { words: 17, items: 5, timeElapsed: '4ms' }
});

Load the JSON from file with your properties names

nss.loadJson("Items.json", "utf8", "itemId", "itemName", "keywords").then(data => {
	// response: { words: 17, items: 5, timeElapsed: '3ms' }
});

Load the JSON from string

let jSonString = `[{"itemName":"WHISKY RED LABEL", "itemId":"1", "keywords": "fancy"},{  
					"itemName":"WHISKY BLACK LABEL", "itemId":"2"}]`;

nss.loadJsonString(jSonString).then(data => {
	// response: { words: 5, items: 2, timeElapsed: '1ms' }
});

Load the JSON from string with additional fields (price, popularity and thumbImg). You can insert any additional field excluding itemId, itemName and keywords.

let jSonString = `[{"itemName":"WHISKY RED LABEL", "itemId":"1", "keywords":"fancy", "price":25.57, "popularity":1, "thumbImg":"whisky-red-label.png"},{  
					"itemName":"WHISKY BLACK LABEL", "itemId":"2", "price":19.99, "popularity":0.9, "thumbImg":"whisky-black-label.png"}]`;

nss.loadJsonString(jSonString).then(data => {
	// response: { words: 5, items: 2, timeElapsed: '2ms' }
});

Load the JSON from string with your properties names

let jSonString = `[{"nm":"WHISKY RED LABEL", "id":"1", "kw": "fancy"},{  
					"nm":"WHISKY BLACK LABEL", "id":"2"}]`;

nss.loadJsonString(jSonString, "id", "nm", "kw").then(data => {
	// response: { words: 5, items: 2, timeElapsed: '2ms' }
});

Load the JSON from string with your properties names and additional fields (price, popularity and thumbImg). You can insert any additional field excluding itemId, itemName and keywords.

let jSonString = `[{"nm":"WHISKY RED LABEL", "id":"1", "kw":"fancy", "price":25.57, "popularity":1, "thumbImg":"whisky-red-label.png"},{  
					"nm":"WHISKY BLACK LABEL", "id":"2", "price":19.99, "popularity":0.9, "thumbImg":"whisky-black-label.png"}]`;

nss.loadJsonString(jSonString, "id", "nm", "kw").then(data => {
	// response: { words: 5, items: 2, timeElapsed: '2ms' }
});

Searching for items

Getting itemsId from searched words.

Examples of how to call the api and responses:

nss.query("whisky").then(data => {
	//response:  { query: 'whisky', words: [ 'whisky' ], missingWords: [], expressions: [], missingExpressions: [], itemsId: [ '1', '2' ], timeElapsed: '1ms' }
});

//did you mean search result with misspelled search criteria
nss.query("wisk").then(data => {
	//response: { query: 'wisk', words: [ 'whisky' ], missingWords: ['wisk'], expressions: [], missingExpressions: [], itemsId: [ '1', '2' ], timeElapsed: '1ms' }
});

//did you mean search result with misspelled search criteria
nss.query("wisk read lbel").then(data => {
	//response: { query: 'Wisk Read Labl', words: [ 'Whisky', 'Red', 'Label' ], missingWords: ['Wisk', 'Read', 'Labl'], expressions: [], missingExpressions: [], itemsId: [ '1' ], timeElapsed: '2ms' }
});

//query with paramenter returnItemsJson = true  
nss.query("whisky", true).then(data => {
	/*response:  { query: 'whisky', words: [ 'whisky' ], missingWords: [], expressions: [], missingExpressions: [], 
		[ 
			{ itemName: 'WHISKY RED LABEL', itemId: '1', keywords: 'fancy' },
			{ itemName: 'WHISKY BLACK LABEL', itemId: '2' } 
		], 
		timeElapsed: '1ms' }
	*/
});

//query with paramenter returnItemsJson = true and ordering by popularity, desc using an object on a database loaded with additional fields
let orderByObject = {field: "popularity", direction: "desc"};

nss.query("whisky", true, orderByObject).then(data => {
	/*response:  { query: 'whisky', words: [ 'whisky' ], missingWords: [], expressions: [], missingExpressions: [], 
		[ 
			{ itemName: 'WHISKY RED LABEL', itemId: '1', keywords: 'fancy', price: 25.57, popularity: 1, thumbImg: 'whisky-red-label.png' },
			{ itemName: 'WHISKY BLACK LABEL', itemId: '2', price: 19.99, popularity: 0.9, thumbImg: 'whisky-black-label.png' } 
		], 
		timeElapsed: '1ms' }
	*/
});

//query with paramenter returnItemsJson = true and ordering by popularity, desc using a function on a database loaded with additional fields
let orderByFunc = ((x, y) => { return x.popularity < y.popularity; });

nss.query("whisky", true, orderByFunc).then(data => {
	/*response:  { query: 'whisky', words: [ 'WHISKY' ], missingWords: [], expressions: [], missingExpressions: [], 
		[ 
			{ itemName: 'WHISKY RED LABEL', itemId: '1', keywords: 'fancy', price: 25.57, popularity: 1, thumbImg: 'whisky-red-label.png' },
			{ itemName: 'WHISKY BLACK LABEL', itemId: '2', price: 19.99, popularity: 0.9, thumbImg: 'whisky-black-label.png' } 
		], 
		timeElapsed: '1ms' }
	*/
});

//quoted search criteria
nss.query("'red label'").then(data => {
	//response: { query: '\'RED LABEL\'', words: [ 'RED', 'LABEL' ], missingWords: [], expressions: [ 'RED LABEL' ], missingExpressions: [], itemsId: [ '1' ], timeElapsed: '1ms' }
});

//quoted search criteria
nss.query("'label red'").then(data => {
	//response: { query: '\'label red\'', words: [ 'label', 'red' ], missingWords: [], expressions: [], missingExpressions: [ 'label red' ], itemsId: [ '1' ], timeElapsed: '2ms' }
});

//dashed search criteria
nss.query("Red-Blood").then(data => {
	//response: { query: 'Red-Blood', words: [ 'Red' ], missingWords: [ 'Blood' ], expressions: [], missingExpressions: [ 'Red-Blood' ], itemsId: [ '1' ], timeElapsed: '2ms' }
});

//slashed search criteria
nss.query("HAM L/S").then(data => {
	//response: { query: 'HAM L/S', words: [ 'HAM', 'L', 'S' ], missingWords: [], expressions: [ 'L/S' ], missingExpressions: [], itemsId: [ '3' ], timeElapsed: '2ms' }
});

//double quoted search criteria
nss.query("\"HAM L/S\"").then(data => {
	//response: { query: '"HAM L/S"', words: [ 'HAM', 'L', 'S' ], missingWords: [], expressions: [ 'HAM L/S' ], missingExpressions: [], itemsId: [ '3' ], timeElapsed: '2ms' }
});

  

Getting words suggestions

Getting words suggestions to fill dropdown boxes or type-ahead text fields.

Examples of how to call the api and responses:

nss.getSuggestedWords("La").then(data => {
	//response: { suggestions: [ 'Label', 'Labely' ], timeElapsed: '1ms' }
});

nss.getSuggestedWords("whi").then(data => {
	//response: { suggestions: [ 'whisky label', 'whisky red', 'whisky black' ], timeElapsed: '1ms' }
});

nss.getSuggestedWords("whisky re").then(data => {
	//response: { suggestions: [ 'whisky red' ], timeElapsed: '2ms' }
});
  

Getting items suggestions

Getting items suggestions to fill dropdown boxes or type-ahead text fields.

Examples of how to call the api and responses:

nss.getSuggestedItems("PARME").then(data => {
	//response: { items: [ { itemId: '4', itemName: 'PESTO PARMESAN HAM' } ], timeElapsed: '2ms' }
});

nss.getSuggestedItems("Whisky fancy").then(data => {
	//response: { items: [ { itemId: '1', itemName:'WHISKY RED LABEL' } ], timeElapsed: '1ms' }
});

nss.getSuggestedItems("whisky re").then(data => {
	//response: { items:[ { itemId: '1', itemName: 'WHISKY RED LABEL' } ], timeElapsed: '1ms' }
});

nss.getSuggestedItems("whisky label").then(data => {
	//response: { items: [ {itemId: '1', itemName: 'WHISKY RED LABEL' }, { itemId: '2', itemName: 'WHISKY BLACK LABEL' } ], timeElapsed: '2ms' }
});

//get one item suggestions ordering by price, asc using a function and omitting the direction.
let orderByObject = {field: "price"};

nss.getSuggestedItems("whisky label", 1, orderByObject).then(data => {
	//response: { items: [ { itemName: 'WHISKY BLACK LABEL', itemId: '2', price: 19.99, popularity: 0.9, thumbImg: 'whisky-black-label.png' } ], timeElapsed: '2ms' }
});
  
//get one item suggestions ordering by price, asc using a function.
let orderByFunc = ((x, y) => { return x.price > y.price; });

nss.getSuggestedItems("whisky label", 1, orderByFunc).then(data => {
	//response: { items: [ { itemName: 'WHISKY BLACK LABEL', itemId: '2', price: 19.99, popularity: 0.9, thumbImg: 'whisky-black-label.png' } ], timeElapsed: '2ms' }
});
  
  

Insert items

Insert a new item into the database.

Examples of how to call the api and responses:

let newItem = {  
	"itemId": "VODKA ABSOLUT",
	"itemName": "6",
	"keywords": "Keyword1, keyword2..."
	};

nss.insertItem(newItem).then(data => {
	//response: { timeElapsed: '2ms' }
});

Insert an item with your properties names.

let newItem = {  
	"id": "VODKA ABSOLUT",
	"nm": "6",
	"kw": "Keyword1, keyword2..."
	};

nss.insertItem(newItem, "id", "nm", "kw").then(data => {
	//response: { timeElapsed: '2ms' }
});

Insert an item with additional fields (price, popularity and thumbImg). You can insert any additional field excluding itemId, itemName and keywords.

let newItem = {  
	"itemId": "VODKA ABSOLUT",
	"itemName": "6",
	"keywords": "Keyword1, keyword2...",
	"price": 25.57,
	"popularity": 1,
	"thumbImg": "vodka-absolute.png"
	};

nss.insertItem(newItem).then(data => {
	//response: { timeElapsed: '2ms' }
});

Remove items

Remove an item from the database.

Examples of how to call the api and responses:

let itemId = "6";

nss.removetItem(itemId).then(data => {
	//response: { timeElapsed: '2ms' }
});

Roadmap

  • Catalog (several dictionaries)
  • More databases support
  • Inject your database plugin
  • Browser version.
  • Translate JS to TS

Pull requests

If you submit a pull request, thanks! There are a couple of rules to follow to make it manageable:

  • The pull request should be atomic, i.e. contain only one feature. If it contains more, please submit multiple pull requests.
  • Please stick to the current coding style. It's important that the code uses a coherent style for readability.
  • Update the readme accordingly.
  • Last but not least: The goal here is simplicity.

Bug reporting guidelines

If you report a bug, thank you! That said for the process to be manageable please strictly adhere to the following guidelines. I'll not be able to handle bug reports that don't:

  • Your bug report should be a self-containing project with a package.json for any dependencies you need. I need to run through a simple npm install; node bugreport.js.
  • It should use assertions to showcase the expected vs actual behavior.
  • Simplify as much as you can. Strip all your application-specific code.
  • Please explain precisely in the issue.
  • The code should be Javascript.

Donations

Please consider donating some if your app is successful or you learned something valuable here.

paypal

Keep in mind that I am maintaining this repository on my free time so thank you for considering a donation. :+1:

1.10.6

5 years ago

1.10.5

5 years ago

1.10.4

5 years ago

1.10.3

5 years ago

1.10.2

6 years ago

1.10.1

6 years ago

1.10.0

6 years ago

1.9.11

6 years ago

1.9.10

6 years ago

1.9.9

6 years ago

1.9.8

6 years ago

1.9.7

6 years ago

1.9.6

6 years ago

1.9.5

6 years ago

1.9.4

6 years ago

1.9.2

7 years ago

1.9.1

7 years ago

1.9.0

7 years ago

1.8.9

7 years ago

1.8.8

7 years ago

1.8.7

7 years ago

1.8.6

7 years ago

1.8.5

7 years ago

1.8.4

7 years ago

1.8.3

7 years ago

1.8.2

7 years ago

1.8.1

7 years ago

1.8.0

7 years ago

1.7.9

7 years ago

1.7.8

7 years ago

1.7.7

7 years ago

1.7.6

7 years ago

1.7.5

7 years ago

1.7.4

7 years ago

1.7.3

7 years ago

1.7.2

7 years ago

1.7.0

8 years ago

1.6.0

8 years ago

1.5.0

8 years ago

1.4.0

8 years ago

1.3.0

8 years ago

1.2.0

8 years ago

1.1.0

8 years ago