diff --git a/lib/sphinxapi.js b/lib/sphinxapi.js index 862881f..27fec77 100644 --- a/lib/sphinxapi.js +++ b/lib/sphinxapi.js @@ -934,8 +934,109 @@ SphinxClient.prototype.BuildExcerpts = function (docs, index, words, opts, cb) { return null; }); }; -SphinxClient.prototype.UpdateAttributes = function (index, attrs, values, mva) { - if (mva === undefined) mva = false; +SphinxClient.prototype.UpdateAttributes = function (index, attrs, values, mva, fn) { +/* === Validation === */ + + assert.equal(typeof index, 'string'); + assert.equal(typeof attrs, 'object'); + assert.equal(typeof values, 'object'); + assert.equal(typeof mva, 'boolean'); + + for (var k in attrs) { + if (!attrs.hasOwnProperty(k)) continue; + + assert.equal(typeof attrs[k], 'string'); + } + + for (var k in values) { + if (!values.hasOwnProperty(k)) continue; + + // Document must be an array of attribute values. + assert.equal(typeof values[k], 'object'); + + // Number of attributes do not match. + assert.equal(len(values[k]), len(attrs)); + + for (var v in values[k]) { + if (!values[k].hasOwnProperty(v)) continue; + + if (mva) { + // MVA must be an array. + assert.equal(typeof values[k][v], 'object'); + + for (var vv in values[k][v]) { + if (!values[k][v].hasOwnProperty(vv)) continue; + + // Attribute value must be numeric. + assert.equal(typeof values[k][v][vv], 'number'); + } + } else { + // Attribute value must be numeric. + assert.equal(typeof values[k][v], 'number'); + } + } + } + +/* === Build request === */ + + var req = []; + + // index + req.push(pack('>L', [len(index)]), index); + + // attrs + req.push(pack('>L', [len(attrs)])); + for (var k in attrs) { + if (!attrs.hasOwnProperty(k)) continue; + + req.push(pack('>L', [len(attrs[k])]), attrs[k]); + req.push(pack('>L', [mva?1:0])); + } + + + // values + req.push(pack('>L', [len(values)])); + for (var k in values) { + if (!values.hasOwnProperty(k)) continue; + + req.push(packUInt64(k)); + + for (var v in values[k]) { + if (!values[k].hasOwnProperty(v)) continue; + + if (mva) { + req.push(pack('>L', [len(values[k][v])])); + + for (var vv in values[k][v]) { + if (!values[k][v].hasOwnProperty(vv)) continue; + + req.push(pack('>L', [values[k][v][vv]])); + } + } else { + req.push(pack('>L', [values[k][v]])); + } + } + } + + var reqData = req.reduce(ReduceBuffer, new Buffer('')); + var length = reqData.length; + +/* Send request */ + + var self = this; + var request = ConcatBuffer(pack('>2HL', [SphinxClient.SEARCHD_COMMAND_UPDATE, SphinxClient.VER_COMMAND_UPDATE, length]), reqData); + this._SendRequest(SphinxClient.VER_COMMAND_UPDATE, request, function (err, response) { + if (err) { + return fn(err, null); + } + if (response.length != 4) { + self._error = 'unexpected response length'; + return fn(err, null); + } + + var amount = Number(unpack('>L', response.slice(0, 4))); + return fn(err, amount); + }); }; SphinxClient.prototype.BuildKeywords = function (query, index, hits, cb ) { assert.equal(typeof query, 'string');