http
Hide Source
var http = require('http'),
https = require('https'),
Query = require('./query'),
Collection = require('./collection'),
querystring = require('querystring'),
format = require('./utils/format'),
SolrError = require('./error/solr-error'),
JSONStream = require('JSONStream'),
duplexer = require('duplexer'),
request = require('request'),
JSONbig = require('json-bigint'),
versionUtils = require('./utils/version');
createClient()
Hide Source
function createClient(host, port, core, path, agent, secure, bigint, solrVersion){
var options = (typeof host === 'object') ? host : {
host : host,
port : port,
core : core,
path : path,
agent : agent,
secure : secure,
bigint : bigint,
solrVersion: solrVersion
};
return new Client(options);
}
Client()
Hide Source
function Client(options){
this.options = {
host : options.host || '127.0.0.1',
port : options.port || '8983',
core : options.core || '',
path : options.path || '/solr',
agent : options.agent,
secure : options.secure || false,
bigint : options.bigint || false,
get_max_request_entity_size: options.get_max_request_entity_size || false,
solrVersion: options.solrVersion || versionUtils.Solr3_2
};
// Default paths of all request handlers
this.UPDATE_JSON_HANDLER = (versionUtils.version(this.options.solrVersion) >= versionUtils.Solr4_0) ? 'update' : 'update/json';
this.UPDATE_HANDLER = 'update';
this.SELECT_HANDLER = 'select';
this.COLLECTIONS_HANDLER = 'admin/collections';
this.ADMIN_PING_HANDLER = 'admin/ping';
this.REAL_TIME_GET_HANDLER = 'get';
this.SPELL_HANDLER = 'spell';
}
Client.prototype.add()
Hide Source
Client.prototype.add = function(docs,options,callback){
if(typeof(options) === 'function'){
callback = options;
options = {};
}
docs = format.dateISOify(docs); // format `Date` object into string understable for Solr as a date.
docs = Array.isArray(docs) ? docs : [docs];
return this.update(docs,options,callback);
};
Client.prototype.realTimeGet()
Hide Source
Client.prototype.realTimeGet = function(ids, query, callback){
if(typeof query === 'function'){
callback = query;
query = {};
}
ids = Array.isArray(ids) ? ids : [ids];
query.ids = ids.join(',');
return this.get(this.REAL_TIME_GET_HANDLER,query,callback);
};
Client.prototype.addRemoteResource()
Hide Source
Client.prototype.addRemoteResource = function(options,callback){
options.parameters = options.parameters || {};
options.format = (options.format === 'xml' ? '' : options.format || ''); // reason: the default route of the XmlUpdateRequestHandle is /update and not /update/xml.
options.parameters.commit = (options.parameters.commit === undefined ? false : options.parameters.commit);
options.parameters['stream.contentType'] = options.contentType || 'text/plain;charset=utf-8';
if(options.path.match(/^https?:\/\//)){
options.parameters['stream.url'] = options.path;
}else{
options.parameters['stream.file'] = options.path;
}
var handler = this.UPDATE_HANDLER + '/' + options.format.toLowerCase();
var query = querystring.stringify(options.parameters);
return this.get(handler,query,callback);
};
Client.prototype.createAddStream()
Hide Source
Client.prototype.createAddStream = function(options){
var path = [this.options.path,this.options.core, this.UPDATE_JSON_HANDLER + '?' + querystring.stringify(options) +'&wt=json']
.filter(function(element){
return element;
})
.join('/');
var headers = {
'content-type' : 'application/json',
'charset' : 'utf-8'
};
if(this.options.authorization){
headers['authorization'] = this.options.authorization;
}
var protocol = this.options.secure ? 'https' : 'http';
var optionsRequest = {
url : protocol + '://' + this.options.host +':' + this.options.port + path ,
method : 'POST',
headers : headers
};
var jsonStreamStringify = JSONStream.stringify();
var postRequest = request(optionsRequest);
jsonStreamStringify.pipe(postRequest);
return duplexer(jsonStreamStringify,postRequest);
};
Client.prototype.commit()
Hide Source
Client.prototype.commit = function(options,callback){
if(typeof(options) === 'function'){
callback = options;
options = {};
}
var data = {
commit : options || {}
};
return this.update(data,callback);
};
Client.prototype.prepareCommit()
Hide Source
Client.prototype.prepareCommit = function(callback){
return this.update({},{ prepareCommit : true},callback);
};
Client.prototype.softCommit()
Hide Source
Client.prototype.softCommit = function(callback){
return this.update({},{ softCommit : true},callback);
};
Client.prototype.delete()
Hide Source
Client.prototype.delete = function(field,text,options,callback) {
if(typeof(options) === 'function'){
callback = options;
options = {};
}
text = format.dateISOify(text);
var data = {
'delete' : {
query : field + ':' + format.escapeSpecialChars(text)
}
};
return this.update(data,options,callback);
};
Client.prototype.deleteByRange()
Hide Source
Client.prototype.deleteByRange = function(field,start,stop,options,callback){
if(typeof(options) === 'function'){
callback = options;
options = {};
}
start = format.dateISOify(start);
stop = format.dateISOify(stop);
var query = field + ':[' + start + ' TO ' + stop + ']';
return this.deleteByQuery(query,options,callback);
};
Client.prototype.deleteByID()
Hide Source
Client.prototype.deleteByID = function(id,options,callback){
if(typeof(options) === 'function'){
callback = options;
options = {};
}
var data = {
'delete' : {
id : id
}
};
return this.update(data,options,callback);
};
Client.prototype.deleteByQuery()
Hide Source
Client.prototype.deleteByQuery = function(query,options,callback){
if(typeof(options) === 'function'){
callback = options;
options = {};
}
var data = {
'delete' : {
query : query
}
};
return this.update(data,options,callback);
};
Client.prototype.deleteAll()
Hide Source
Client.prototype.deleteAll = function(options,callback){
return this.deleteByQuery('*:*',options,callback);
};
Client.prototype.optimize()
Hide Source
Client.prototype.optimize = function(options,callback){
if(typeof(options) === 'function'){
callback = options;
options = {};
}
var data = {
optimize : options || {}
};
return this.update(data,callback);
};
Client.prototype.rollback()
Hide Source
Client.prototype.rollback = function(callback){
var data = {
rollback : {}
};
return this.update(data,callback);
};
Client.prototype.update()
Hide Source
Client.prototype.update = function(data,options,callback){
if(typeof(options) === 'function'){
callback = options;
options = {};
}
var json = pickJSON(this.options.bigint).stringify(data);
var fullPath = [this.options.path,this.options.core, this.UPDATE_JSON_HANDLER + '?' + querystring.stringify(options) +'&wt=json']
.filter(function(element){
return element;
})
.join('/');
var params = {
host : this.options.host,
port : this.options.port,
fullPath : fullPath,
json : json,
secure : this.options.secure,
bigint : this.options.bigint,
authorization : this.options.authorization,
agent : this.options.agent
};
return postJSON(params,callback);
};
Client.prototype.search()
Hide Source
Client.prototype.search = function(query,callback){
return this.get(this.SELECT_HANDLER, query, callback);
};
Client.prototype.executeCollection()
Hide Source
Client.prototype.executeCollection = function(collection,callback){
return this.get(this.COLLECTIONS_HANDLER, collection, callback);
};
Client.prototype.searchAll()
Hide Source
Client.prototype.searchAll = function(callback){
return this.search('q=*', callback);
};
Client.prototype.spell()
Spellcheck is also enabled.
Hide Source
Client.prototype.spell = function(query,callback){
return this.get(this.SPELL_HANDLER, query, callback);
};
Client.prototype.get()
Hide Source
Client.prototype.get = function(handler,query,callback){
var parameters = '';
if(typeof query === 'function'){
callback = query;
}else if((query instanceof Query) || (query instanceof Collection)){
parameters += query.build();
}else if(typeof query === 'object'){
parameters += querystring.stringify(query);
}else if(typeof query === 'string'){
parameters += query;
}
var pathArray;
if(handler != 'admin/collections'){
pathArray = [this.options.path,this.options.core,handler + '?' + parameters + '&wt=json'];
} else {
pathArray = [this.options.path,handler + '?' + parameters + '&wt=json'];
}
var fullPath = pathArray.filter(function(element){
return element;
}).join('/');
var approxUrlLength = 10 + Buffer.byteLength(this.options.host) + (this.options.port+"").length + Buffer.byteLength(fullPath); // Buffer (10) accounts for protocol and special characters like ://, port colon, and initial slash etc
if (this.options.get_max_request_entity_size === false || approxUrlLength <= this.options.get_max_request_entity_size) {
var params = {
host: this.options.host,
port: this.options.port,
fullPath: fullPath,
secure: this.options.secure,
bigint: this.options.bigint,
authorization: this.options.authorization,
agent: this.options.agent
};
return getJSON(params, callback);
} else {
// Funnel this through a POST because it's too large
return this.post(handler, query, callback);
}
};
Client.prototype.post()
Hide Source
Client.prototype.post = function(handler,query,callback){
var parameters = '';
if(typeof query === 'function'){
callback = query;
}else if(query instanceof Query){
parameters += query.build();
}else if(typeof query === 'object'){
parameters += querystring.stringify(query);
}else if(typeof query === 'string'){
parameters += query;
}
var pathArray;
if(handler != 'admin/collections'){
pathArray = [this.options.path,this.options.core,handler + '?' + parameters + '&wt=json'];
} else {
pathArray = [this.options.path,handler + '?' + parameters + '&wt=json'];
}
var fullPath = pathArray.filter(function(element){
return element;
}).join('/');
var params = {
host : this.options.host,
port : this.options.port,
fullPath : fullPath,
params : parameters,
secure : this.options.secure,
bigint : this.options.bigint,
authorization : this.options.authorization,
agent : this.options.agent
};
return postForm(params,callback);
};
Client.prototype.ping()
Hide Source
Client.prototype.ping = function(callback){
return this.get(this.ADMIN_PING_HANDLER, callback);
};
postJSON()
Hide Source
function postJSON(params,callback){
var headers = {
'content-type' : 'application/json; charset=utf-8',
'content-length': Buffer.byteLength(params.json),
'accept' : 'application/json; charset=utf-8'
};
if(params.authorization){
headers['authorization'] = params.authorization;
}
var options = {
host : params.host,
port : params.port,
method : 'POST',
headers : headers,
path : params.fullPath
};
if(params.agent !== undefined){
options.agent = params.agent;
}
var request = pickProtocol(params.secure).request(options);
request.on('response', handleJSONResponse(request, params.bigint, callback));
request.on('error',function onError(err){
if (callback) callback(err,null);
});
request.write(params.json);
request.end();
return request;
}
postForm()
Hide Source
function postForm(params,callback){
var headers = {
'content-type' : 'application/x-www-form-urlencoded; charset=utf-8',
'content-length': Buffer.byteLength(params.params),
'accept' : 'application/json; charset=utf-8'
};
if(params.authorization){
headers['authorization'] = params.authorization;
}
var options = {
host : params.host,
port : params.port,
method : 'POST',
headers : headers,
path : params.fullPath
};
if(params.agent !== undefined){
options.agent = params.agent;
}
var request = pickProtocol(params.secure).request(options);
request.on('response', handleJSONResponse(request, params.bigint, callback));
request.on('error',function onError(err){
if (callback) callback(err,null);
});
request.write(params.params);
request.end();
return request;
}
getJSON()
Hide Source
function getJSON(params,callback){
var headers = {
'accept' : 'application/json; charset=utf-8'
};
var options = {
host : params.host,
port : params.port,
path : params.fullPath,
headers : headers
};
if(params.agent !== undefined){
options.agent = params.agent;
}
if(params.authorization){
var headers = {
'authorization' : params.authorization
};
options.headers = headers;
}
var request = pickProtocol(params.secure).get(options);
request.on('response', handleJSONResponse(request, params.bigint, callback));
request.on('error',function(err){
if (callback) callback(err,null);
});
return request;
}
handleJSONResponse()
Hide Source
function handleJSONResponse(request, bigint, callback){
return function onJSONResponse(response){
var text = '';
var err = null;
var data = null;
// This properly handles multi-byte characters
response.setEncoding('utf-8');
response.on('data',function(chunk){
text += chunk;
});
response.on('end',function(){
if(response.statusCode < 200 || response.statusCode > 299){
err = new SolrError(request,response,text);
if(callback) callback(err,null);
}else{
try{
data = pickJSON(bigint).parse(text);
}catch(error){
err = error;
}finally{
if(callback) callback(err,data);
}
}
});
};
}