itemsjs
Version:
Created to perform fast search on small json dataset (up to 1000 elements).
219 lines (178 loc) • 5.81 kB
JavaScript
"use strict";
var _ = require('./../vendor/lodash');
var helpers = require('./helpers');
var FastBitSet = require('fastbitset');
/**
* search by filters
*/
module.exports.search = function (items, input, configuration, fulltext, facets) {
input = input || {};
var per_page = parseInt(input.per_page || 12);
var 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');
}
var search_time = 0;
var total_time_start = new Date().getTime();
var query_ids; // all ids bitmap
var filtered_indexes_bitmap = facets.bits_ids();
var _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)) {
var 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);
}
var facets_time = new Date().getTime();
var 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
// -------------------------------------
var filtered_indexes = filtered_indexes_bitmap.array();
var filtered_items = filtered_indexes.map(function (_id) {
return facets.get_item(_id);
});
/**
* sorting items
*/
var paginationApplied = false;
var sorting_start_time = new Date().getTime();
var 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(function (v) {
return filtered_indexes_bitmap.has(v);
});
var filtered_items_indexes = filtered_indexes.slice((page - 1) * per_page, page * per_page);
filtered_items = filtered_items_indexes.map(function (_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;
var 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) {
var per_page = options.per_page || 10;
var minimum = options.minimum || 0;
var page = options.page || 1;
var item;
for (var 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');
}
var field = options.field;
var sorted_items = [];
for (var _i = 0; _i < items.length; ++_i) {
if (items[_i].id !== id) {
var 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) {
var per_page = input.per_page || 10;
var page = input.page || 1;
if (input.name && (!configuration.aggregations || !configuration.aggregations[input.name])) {
throw new Error('Please define aggregation "'.concat(input.name, '" in config'));
}
var 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;
var result = module.exports.search(items, search_input, configuration, fulltext, facets);
var 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)
}
};
};