Comparing version
217
lib/Model.js
const Bluebird = require('bluebird') | ||
const debug = require('debug')('hequelize:Model') | ||
// const debug = require('debug')('hequelize:Model') | ||
const _ = require('lodash') | ||
@@ -12,86 +12,18 @@ const HBase = require('hbase-rpc-client') | ||
class Model { | ||
/** | ||
* Creates an instance of Model. | ||
* | ||
* @param {string} rowKey the row key | ||
* @param {object} values like { 'cf:col': 'value } | ||
* @memberof Model | ||
*/ | ||
constructor (rowKey, values = {}) { | ||
this.Model = this.constructor | ||
this.modelOptions = this.constructor.options | ||
this.tableName = this.modelOptions.tableName | ||
this.client = this.Model.hequelize.hbaseClient | ||
this.rowKey = rowKey | ||
this.data = _.clone(this.modelOptions.defaultData) | ||
this.modelOptions.columns.forEach(colOption => { | ||
const col = colOption.name | ||
Object.defineProperty(this, col, { | ||
get () { | ||
const getter = this.modelOptions.columnsObject[col].get | ||
if (getter) { | ||
return getter(this.data[col]) | ||
} | ||
return this.data[col] | ||
}, | ||
set (value) { | ||
switch (colOption.type) { | ||
case 'date': | ||
this.data[col] = new Date(Number(value)) | ||
break | ||
case 'number': | ||
this.data[col] = Number(value) | ||
break | ||
case 'string': | ||
this.data[col] = String(value) | ||
break | ||
case 'buffer': | ||
this.data[col] = Buffer.from(value) | ||
break | ||
} | ||
debug(`set column ${col} to value: ${this.data[col]}`) | ||
} | ||
}) | ||
}) | ||
_.forOwn(this.data, (v, k) => { | ||
const value = values[k] | ||
if (typeof value !== 'undefined') { | ||
this[k] = value | ||
} | ||
}) | ||
} | ||
static init (options = {}) { | ||
this.options = _.defaultsDeep(options, { | ||
classMethods: {}, | ||
instanceMethods: {} | ||
}) | ||
_.assign(this, _.defaultsDeep(options, { | ||
classMethods: {} | ||
})) | ||
const defaultData = this.options.defaultData = {} | ||
this.options.columnNames = [] | ||
this.options.columnsObject = {} | ||
this.columnNames = [] | ||
this.columnsObject = {} | ||
this.options.columns.forEach(col => { | ||
this.options.columnsObject[col.name] = col | ||
this.options.columnNames.push(col.name) | ||
if (col.defaultValue) { | ||
// If default value is function, it will be executed before save method | ||
defaultData[col.name] = col.defaultValue | ||
} else { | ||
defaultData[col.name] = null | ||
} | ||
this.columns.forEach(col => { | ||
this.columnsObject[col.name] = col | ||
this.columnNames.push(col.name) | ||
}) | ||
_.forOwn(this.options.classMethods, (fn, fnName) => { | ||
_.forOwn(this.classMethods, (fn, fnName) => { | ||
this[fnName] = fn | ||
}) | ||
_.forOwn(this.options.instanceMethods, (fn, fnName) => { | ||
this.prototype[fnName] = fn | ||
}) | ||
} | ||
@@ -112,8 +44,7 @@ | ||
* @param {object} [options.columns = all_columns] | ||
* @returns {Model} instance of this | ||
* @memberof Model | ||
* @returns {object} return object | ||
*/ | ||
static async get (rowKey, options) { | ||
options = _.defaults(options, { | ||
columns: this.options.columnNames | ||
columns: this.columnNames | ||
}) | ||
@@ -128,15 +59,11 @@ | ||
const raw = await this.client.getAsync(this.options.tableName, get) | ||
const raw = await this.client.getAsync(this.tableName, get) | ||
if (!raw) { | ||
return null | ||
} | ||
return this.build(rowKey, processRaw(raw)) | ||
return this.formatAfterGet(raw) | ||
} | ||
static async put (rowKey, values, options) { | ||
const instance = this.build(rowKey, values, options) | ||
const columns = [] | ||
const deleteColumns = [] | ||
_.forOwn(values, (value, col) => { | ||
@@ -149,41 +76,16 @@ if (value === undefined || value === null) { | ||
}) | ||
return instance.save(_.assign({ columns, deleteColumns }, options)) | ||
} | ||
async save (options) { | ||
options = _.defaults(options, { | ||
columns: this.modelOptions.columnNames | ||
}) | ||
const put = new HBase.Put(this.rowKey) | ||
options.columns.forEach(col => { | ||
let value | ||
const sourceValue = this.data[col] | ||
if (columns.length > 0) { | ||
const put = new HBase.Put(rowKey) | ||
columns.forEach(col => { | ||
const value = values[col] | ||
const [cf, q] = split(col) | ||
put.add(cf, q, this.formatCellForPut(value, this.columnsObject[col].type)) | ||
}) | ||
await this.client.putAsync(this.tableName, put) | ||
} | ||
const [cf, q] = split(col) | ||
const colOption = this.modelOptions.columnsObject[col] | ||
switch (colOption.type) { | ||
case 'string': | ||
value = String(sourceValue) | ||
break | ||
case 'date': | ||
value = String(sourceValue.getTime()) | ||
break | ||
case 'buffer': | ||
if (sourceValue !== null) { | ||
value = Buffer.from(sourceValue) | ||
} | ||
break | ||
case 'number': | ||
value = String(sourceValue) | ||
break | ||
default: | ||
value = String(sourceValue) | ||
} | ||
put.add(cf, q, value) | ||
debug(`save#put add ${cf}:${q} with value ${value}`) | ||
}) | ||
if (options.deleteColumns.length > 0) { | ||
const del = new HBase.Delete(this.rowKey) | ||
options.deleteColumns.forEach(col => { | ||
if (deleteColumns.length > 0) { | ||
const del = new HBase.Delete(rowKey) | ||
deleteColumns.forEach(col => { | ||
const [cf, q] = split(col) | ||
@@ -194,5 +96,2 @@ del.deleteColumns(cf, q) | ||
} | ||
await this.client.putAsync(this.tableName, put) | ||
return this | ||
} | ||
@@ -209,3 +108,2 @@ | ||
* @returns {Array<Model>} | ||
* @memberof Model | ||
*/ | ||
@@ -224,3 +122,3 @@ static async scan (options) { | ||
const scanner = this.client.getScanner(this.options.tableName, startRow, stopRow) | ||
const scanner = this.client.getScanner(this.tableName, startRow, stopRow) | ||
Bluebird.promisifyAll(scanner) | ||
@@ -231,4 +129,3 @@ | ||
if (tmp && tmp.row) { | ||
const rowKey = tmp.row.toString() | ||
results.push(this.build(rowKey, processRaw(tmp))) | ||
results.push(tmp) | ||
count++ | ||
@@ -240,18 +137,60 @@ } else { | ||
return results | ||
return results.map(item => this.formatAfterGet(item)) | ||
} | ||
static build (rowKey, values, options) { | ||
return new this(rowKey, values, options) | ||
static formatAfterGet (raw) { | ||
if (!raw) { | ||
return null | ||
} | ||
const rawObject = processRaw(raw) | ||
const ret = {} | ||
this.columns.forEach(col => { | ||
ret[col.name] = this.formatCellForGet(rawObject[col.name], col.type) | ||
}) | ||
return ret | ||
} | ||
toJSON () { | ||
return { | ||
rowKey: this.rowKey, | ||
data: this.data | ||
static formatCellForGet (value, type) { | ||
if (!type) { | ||
return value | ||
} | ||
if (typeof value === 'undefined') { | ||
return null | ||
} | ||
switch (type) { | ||
case 'string': | ||
return String(value) | ||
case 'number': | ||
return Number(value) | ||
case 'buffer': | ||
return value | ||
case 'date': | ||
return new Date(Number(value)) | ||
default: | ||
return value | ||
} | ||
} | ||
static formatCellForPut (value, type) { | ||
if (typeof value === 'undefined' || value === null) { | ||
return value | ||
} | ||
switch (type) { | ||
case 'date': | ||
return String(value.getTime()) | ||
case 'buffer': | ||
return value | ||
default: | ||
return String(value) | ||
} | ||
} | ||
} | ||
function processRaw (raw) { | ||
if (!raw) { | ||
return null | ||
} | ||
return raw.columns.reduce((acc, col) => { | ||
@@ -258,0 +197,0 @@ acc[`${col.family}:${col.qualifier}`] = col.value |
{ | ||
"name": "hequelize", | ||
"version": "0.0.1-alpha.3", | ||
"version": "0.0.1-alpha.4", | ||
"description": "Simple HBase ORM based on hbase-rpc-client", | ||
@@ -10,3 +10,3 @@ "main": "index.js", | ||
"scripts": { | ||
"test": "ava" | ||
"test": "./node_modules/.bin/standard && ava" | ||
}, | ||
@@ -25,10 +25,11 @@ "repository": { | ||
"dependencies": { | ||
"bluebird": "^3.5.1", | ||
"debug": "^3.1.0", | ||
"hbase-rpc-client": "^0.1.10", | ||
"lodash": "^4.17.4", | ||
"uuid": "^3.1.0" | ||
"bluebird": "3.5.1", | ||
"debug": "3.1.0", | ||
"hbase-rpc-client": "0.1.10", | ||
"lodash": "4.17.4", | ||
"uuid": "3.1.0" | ||
}, | ||
"devDependencies": { | ||
"ava": "^0.22.0" | ||
"ava": "^0.22.0", | ||
"standard": "^10.0.3" | ||
}, | ||
@@ -35,0 +36,0 @@ "ava": { |
@@ -1,2 +0,1 @@ | ||
const _ = require('lodash') | ||
const test = require('ava') | ||
@@ -37,4 +36,3 @@ const uuid = require('uuid/v4') | ||
const record = await hb.Test.tomGet(fileId) | ||
t.is(record['cf1:string'], value + fileId) | ||
}) |
@@ -23,11 +23,7 @@ const _ = require('lodash') | ||
t.true(_.isDate(ret['cf2:date'])) | ||
t.deepEqual(ret.toJSON(), { | ||
rowKey, | ||
data: { | ||
'cf1:string': stringValue, | ||
'cf2:date': dateValue, | ||
'cf2:buffer': null, | ||
'cf2:number': null | ||
} | ||
t.deepEqual(ret, { | ||
'cf1:string': stringValue, | ||
'cf2:date': dateValue, | ||
'cf2:buffer': null, | ||
'cf2:number': null | ||
}) | ||
@@ -50,11 +46,8 @@ }) | ||
const ret = await hb.Test.get(rowKey) | ||
t.deepEqual(ret.toJSON(), { | ||
rowKey, | ||
data: { | ||
'cf1:string': null, | ||
'cf2:date': null, | ||
'cf2:buffer': null, | ||
'cf2:number': 123 | ||
} | ||
t.deepEqual(ret, { | ||
'cf1:string': null, | ||
'cf2:date': null, | ||
'cf2:buffer': null, | ||
'cf2:number': 123 | ||
}) | ||
}) |
const Hequelize = require('../lib/Hequelize') | ||
const hbase = new Hequelize({ | ||
zkHosts: 'localhost:2181' | ||
zookeeperHosts: 'localhost:2181' | ||
}) | ||
@@ -5,0 +5,0 @@ |
@@ -34,3 +34,2 @@ const _ = require('lodash') | ||
rowKeys.slice(0, 101).forEach((rowKey, index) => { | ||
t.is(results[index].rowKey, rowKeys[index]) | ||
t.is(results[index]['cf1:string'], 'tomtest' + index) | ||
@@ -37,0 +36,0 @@ }) |
11924
-20.97%2
100%10
-16.67%366
-22.13%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated
Updated
Updated