UNPKG

itemsjs

Version:

Created to perform fast search on small json dataset (up to 1000 elements).

236 lines (190 loc) 5.87 kB
const _ = require('./../vendor/lodash'); const helpers = require('./helpers'); const FastBitSet = require('fastbitset'); /** * search by filters */ module.exports.search = function(items, input, configuration, fulltext, facets) { input = input || {}; const per_page = parseInt(input.per_page || 12); const page = parseInt(input.page || 1); if (configuration.native_search_enabled === false && (input.query || input.filter)) { throw new Error('"query" and "filter" options are not working once native search is disabled'); } let search_time = 0; const total_time_start = new Date().getTime(); let query_ids; // all ids bitmap let filtered_indexes_bitmap = facets.bits_ids(); let _ids; if (input._ids) { query_ids = new FastBitSet(input._ids); _ids = input._ids; } else if (input.ids) { _ids = facets.internal_ids_from_ids_map(input.ids); //console.log(_ids); query_ids = new FastBitSet(_ids); } else if (fulltext && (input.query || input.filter)) { const search_start_time = new Date().getTime(); _ids = fulltext.search(input.query, input.filter); search_time = new Date().getTime() - search_start_time; query_ids = new FastBitSet(_ids); } let facets_time = new Date().getTime(); const facet_result = facets.search(input, { query_ids: query_ids }); facets_time = new Date().getTime() - facets_time; if (query_ids) { filtered_indexes_bitmap = query_ids; } if (facet_result.ids) { filtered_indexes_bitmap = filtered_indexes_bitmap.new_intersection(facet_result.ids); } if (facet_result.not_ids) { filtered_indexes_bitmap = filtered_indexes_bitmap.new_difference(facet_result.not_ids); } // new filters to items // ------------------------------------- let filtered_indexes = filtered_indexes_bitmap.array(); let filtered_items = filtered_indexes.map(_id => { return facets.get_item(_id); }); /** * sorting items */ let paginationApplied = false; const sorting_start_time = new Date().getTime(); let sorting_time = 0; if (input.sort) { filtered_items = module.exports.sorted_items(filtered_items, input.sort, configuration.sortings); } else { if (_ids) { filtered_indexes = _ids.filter(v => { return filtered_indexes_bitmap.has(v); }); const filtered_items_indexes = filtered_indexes.slice((page - 1) * per_page, page * per_page); filtered_items = filtered_items_indexes.map(_id => { return facets.get_item(_id); }); paginationApplied = true; } } // pagination if (!paginationApplied) { filtered_items = filtered_items.slice((page - 1) * per_page, page * per_page); } sorting_time = new Date().getTime() - sorting_start_time; const total_time = new Date().getTime() - total_time_start; //console.log(facet_result); return { pagination: { per_page: per_page, page: page, total: filtered_indexes.length }, timings: { total: total_time, facets: facets_time, //filter: filter_time, search: search_time, sorting: sorting_time }, data: { items: filtered_items, //aggregations: aggregations, aggregations: helpers.getBuckets(facet_result, input, configuration.aggregations), } }; }; /** * return items by sort */ module.exports.sorted_items = function(items, sort, sortings) { if (sortings && sortings[sort]) { sort = sortings[sort]; } if (sort.field) { return _.orderBy( items, sort.field, sort.order || 'asc' ); } return items; }; /** * returns list of elements in aggregation * useful for autocomplete or list all aggregation options */ module.exports.similar = function(items, id, options) { const per_page = options.per_page || 10; const minimum = options.minimum || 0; const page = options.page || 1; let item; for (let i = 0 ; i < items.length ; ++i) { if (items[i].id == id) { item = items[i]; break; } } if (!options.field) { throw new Error('Please define field in options'); } const field = options.field; let sorted_items = []; for (let i = 0 ; i < items.length ; ++i) { if (items[i].id !== id) { const intersection = _.intersection(item[field], items[i][field]); if (intersection.length >= minimum) { sorted_items.push(items[i]); sorted_items[sorted_items.length - 1].intersection_length = intersection.length; } } } sorted_items = _.orderBy( sorted_items, ['intersection_length'], ['desc'] ); return { pagination: { per_page: per_page, page: page, total: sorted_items.length }, data: { items: sorted_items.slice((page - 1) * per_page, page * per_page), } }; }; /** * returns list of elements in specific facet * useful for autocomplete or list all aggregation options */ module.exports.aggregation = function (items, input, configuration, fulltext, facets) { const per_page = input.per_page || 10; const page = input.page || 1; if (input.name && (!configuration.aggregations || !configuration.aggregations[input.name])) { throw new Error('Please define aggregation "'.concat(input.name, '" in config')); } const search_input = helpers.clone(input); search_input.page = 1; search_input.per_page = 0; if (!input.name) { throw new Error('field name is required'); } configuration.aggregations[input.name].size = 10000; const result = module.exports.search(items, search_input, configuration, fulltext, facets); const buckets = result.data.aggregations[input.name].buckets; return { pagination: { per_page: per_page, page: page, total: buckets.length }, data: { buckets: buckets.slice((page - 1) * per_page, page * per_page) } }; };