UNPKG

nolr

Version:

Solr Node Client with ES6 Support

417 lines (384 loc) 10.9 kB
/** * forked from Solr-Node on 2018.8.1 by Seech */ /*jshint browser:false*/ /** * Require modules */ const _ = require('underscore'); const fetch = require('node-fetch'); const logger = require('log4js').getLogger('nolr'); const QueryString = require('querystring'); const Query = require('./query'); /** * Solr Node Client * * @constructor * * @param {Object} options * @param {String} [options.host] - host address of Solr server * @param {Number|String} [options.port] - port number of Solr server * @param {String} [options.core] - client core name * @param {String} [options.rootPath] - solr root path * @param {String} [options.protocol] - request protocol ('http'|'https') * @param {String} [options.debugLevel] - log4js debug level ('ALL'|'DEBUG'|'INFO'|'ERROR'|...) */ function Client(options) { this.options = { host: options.host || '127.0.0.1', port: options.port || '8983', core: options.core || '', rootPath: options.rootPath || 'solr', protocol: options.protocol || 'http' }; if (options.debugLevel) { logger.setLevel(options.debugLevel); } // Path Constants List this.SEARCH_PATH = 'select'; this.TERMS_PATH = 'terms'; this.SPELL_PATH = 'spell'; this.MLT_PATH = 'mlt'; this.UPDATE_JSON_SINGLE_DOC_PATH = 'update/json/docs'; this.UPDATE_JSON_ARRAY_PATH = 'update/json'; this.UPDATE_EXTRACT_PATH = 'update/extract'; this.PING_PATH = 'admin/ping'; } /** * Make host url * @private * * @param {String} protocol - protocol ('http'|'https') * @param {String} host - host address * @param {String|Number} port - port number * * @returns {String} */ Client.prototype._makeHostUrl = function(protocol, host, port) { if (port) { return protocol + '://' + host + ':' + port; } else { return protocol + '://' + host; } }; /** * Request get * * @param {String} path - target path * @param {Object|String} query - query * @param {Function} finalCallback - (err, result) * * @returns {undefined|Promise} - When there's no callback function it returns a PromiseŰ */ Client.prototype._requestGet = function(path, query, finalCallback) { var params, options, requestPrefixUrl, requestFullPath; if (query instanceof Query) { params = query.toString(); } else if (_.isString(query)) { params = query; } else { params = 'q=*:*'; } requestPrefixUrl = this._makeHostUrl(this.options.protocol, this.options.host, this.options.port); requestPrefixUrl += '/' + [this.options.rootPath, this.options.core, path].join('/'); requestFullPath = requestPrefixUrl + '?' + params; logger.debug('[_requestGet] requestFullPath: ', requestFullPath); options = { method: 'GET', headers: { 'accept' : 'application/json; charset=utf-8' } }; var result = fetch(requestFullPath, options) .then(function(res) { if (res.status !== 200) { logger.error(res); throw new Error('Solr server error: ' + res.status); } else { return res.json(); } }); if (typeof finalCallback === 'function') { result .then(function(json) { finalCallback(null,json); }) .catch(function (err) { finalCallback(err.message); }); } else { return result; } }; /** * Request post * * @param {String} path - target path * @param {Object} data - json data * @param {Object|String} urlOptions - url options * @param {Function} finalCallback - (err, result) * * @returns {undefined|Promise} - When there's no callback function it returns a PromiseŰ */ Client.prototype._requestPost = function(path, data, urlOptions, finalCallback) { var params, options, requestPrefixUrl, requestFullPath; if (_.isString(urlOptions)) { params = urlOptions; } else if (_.isObject(urlOptions)) { params = QueryString.stringify(urlOptions); } else { params = ''; } requestPrefixUrl = this._makeHostUrl(this.options.protocol, this.options.host, this.options.port); requestPrefixUrl += '/' + [this.options.rootPath, this.options.core, path].join('/'); requestFullPath = requestPrefixUrl + '?' + params; logger.debug('[_requestPost] requestFullPath: ', requestFullPath); logger.debug('[_requestPost] data: ', data); options = { method: 'POST', body: JSON.stringify(data), headers: { 'accept' : 'application/json; charset=utf-8', 'content-type' : 'application/json; charset=utf-8' } }; var result = fetch(requestFullPath, options) .then(function(res) { if (res.status !== 200) { throw new Error('Solr server error: ' + res.status); } else { return res.json(); } }); if (typeof finalCallback === 'function') { result .then(function(json) { finalCallback(null,json); }) .catch(function (err) { finalCallback(err.message); }); } else { return result; } }; /** * Make Query instance and return * * @returns {Object} */ Client.prototype.query = function() { return new Query(); }; /** * Search * * @param {Object|String} query * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.search = function(query, finalCallback) { if (typeof finalCallback === 'function') { this._requestGet(this.SEARCH_PATH, query, finalCallback); } else { return this._requestGet(this.SEARCH_PATH, query); } }; /** * Terms * * @param {Object|String} query * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.terms = function(query, finalCallback) { if (typeof finalCallback === 'function') { this._requestGet(this.TERMS_PATH, query, finalCallback); } else { return this._requestGet(this.TERMS_PATH, query); } }; /** * Mlt * * @param {Object|String} query * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.mlt = function(query, finalCallback) { if (typeof finalCallback === 'function') { this._requestGet(this.MLT_PATH, query, finalCallback); } else { return this._requestGet(this.MLT_PATH, query); } }; /** * Spell * * @param {Object|String} query * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.spell = function(query, finalCallback) { if (typeof finalCallback === 'function') { this._requestGet(this.SPELL_PATH, query, finalCallback); } else { return this._requestGet(this.SPELL_PATH, query); } }; /** * Update Arrary * * @param {Object} data - json data * @param {Object|Function} [options] - update options * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.updateMany = function(data, options, finalCallback) { var bodyData; if (arguments.length < 3 && _.isFunction(options)) { finalCallback = options; options = { commit: true }; // 'commit:true' option is default } bodyData = { add: { doc: data, overwrite: true } }; if (typeof finalCallback === 'function') { this._requestPost(this.UPDATE_JSON_ARRAY_PATH, bodyData, options, finalCallback); } else { return this._requestPost(this.UPDATE_JSON_ARRAY_PATH, bodyData, options); } }; /** * updateOne * * @param {Object} data - json data * @param {Object|Function} [options] - update options * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.updateOne = function(data, options, finalCallback) { var bodyData = data; if (arguments.length < 3 && _.isFunction(options)) { finalCallback = options; options = { wt: 'json', commit: true }; // 'commit:true' option is default } if (typeof finalCallback === 'function') { this._requestPost(this.UPDATE_JSON_SINGLE_DOC_PATH, bodyData, options, finalCallback); } else { return this._requestPost(this.UPDATE_JSON_SINGLE_DOC_PATH, bodyData, options); } }; /** * Update Extract (files to be indexed via Tika using stream.* param) * * @param {Object|Function} [options] - update options * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.updateExtract = function(options, finalCallback) { var bodyData; if (arguments.length < 2 && _.isFunction(options)) { finalCallback = options; options = { commit: true }; // 'commit:true' option is default } // We need JSON response options.wt = "json"; bodyData = { add: { doc: null, overwrite: true } }; if (typeof finalCallback === 'function') { this._requestPost(this.UPDATE_EXTRACT_PATH, bodyData, options, finalCallback); } else { return this._requestPost(this.UPDATE_EXTRACT_PATH, bodyData, options); } }; /** * Delete * * @param {String|Object} query - query * @param {Object|Function} [options] - delete options * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.delete = function(query, options, finalCallback) { var bodyData, bodyQuery; if (arguments.length < 3 && _.isFunction(options)) { finalCallback = options; options = { commit: true }; // 'commit:true' option is default } if (_.isString(query)) { bodyQuery = query; } else if (_.isObject(query)) { bodyQuery = QueryString.stringify(query, ' AND ', ':'); } else { bodyQuery = ''; } bodyData = { 'delete': { query: bodyQuery } }; if (typeof finalCallback === 'function') { this._requestPost(this.UPDATE_JSON_SINGLE_DOC_PATH, bodyData, options, finalCallback); } else { return this._requestPost(this.UPDATE_JSON_SINGLE_DOC_PATH, bodyData, options); } }; /** * Ping * * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.ping = function(finalCallback) { if (typeof finalCallback === 'function') { this._requestGet(this.PING_PATH, '', finalCallback); } else { return this._requestGet(this.PING_PATH, ''); } }; /** * Commit * * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.commit = function(finalCallback) { if (typeof finalCallback === 'function') { this._requestPost(this.UPDATE_JSON_SINGLE_DOC_PATH, {}, {commit: true}, finalCallback); } else { return this._requestPost(this.UPDATE_JSON_SINGLE_DOC_PATH, {}, {commit: true}); } }; /** * SoftCommit * * @param {Function} finalCallback - (err, result) * * @returns {Undefined|Promise} */ Client.prototype.softCommit = function(finalCallback) { if (typeof finalCallback === 'function') { this._requestPost(this.UPDATE_JSON_SINGLE_DOC_PATH, {}, {softCommit: true}, finalCallback); } else { return this._requestPost(this.UPDATE_JSON_SINGLE_DOC_PATH, {}, {softCommit: true}); } }; module.exports = Client;