本文适合对ES6有一定了解且对elasticsearch官方文档api有一定了解的人群阅读
1.连接elasticsearch
/****
* 获取数据源
*/
const es = require('elasticsearch');
const confES = require('../configure.js').elasticsearch;
const esDataSource = new es.Client({
host: confES.host,
});
exports.esDataSource=esDataSource;
2.使用async对elasticsearch api 进行包装
const esDataSource = require('./connectES.js').esDataSource;
const RedisUtil = require('./redisUtil.js').RedisUtil;
const constantESCode = require('./constant.js');
/****
*
* @param
index: String,//索引位置
type: String,//索引类型
id: Number,//索引id
size: Number,//需要搜索的索引数目
body: Object,//插入的类型
* @version 1.0 操作elasticsearch的常用操作 2017-7-11
*
*/
class EsUtil {
/**
*
* @param {index, type, body, condition }
* @param condition 用于判断是否存在相同记录的条件,选填项
* @version 1.0 2017-7-11 插入操作
* @return {code 状态码,data 数据}
*/
static async insertES({ index, type, body, condition }) {
let commonStruct = {
index: index,
type: type,
}
//判断是否需要判断相同
if (!Object.is(condition, undefined)) {
let s = Object.assign(commonStruct, { condition });
let res = await EsUtil.searchES(s);
let hits = res.data.hits;
if (!Object.is(hits, undefined) && hits.total > 0) {
//不执行存储
return { code: constantESCode.esCode.existCode };
}
}
//获取序列化Redis id 这边采用的redis生成自增id 这边可以自定义修改
let sequceneId = await RedisUtil.incrKey(type);
if (!Number.isInteger(sequceneId)) {
return { code: constantESCode.esCode.sequenceIdCode };
}
let obj = Object.assign(commonStruct, { id: sequceneId }, { body, });
return await new Promise((resolve, reject) => {
esDataSource.index(obj, (err, data) => {
if (err) {
reject({ code: constantESCode.esCode.insertFailCode, err });
} else {
resolve({ code: constantESCode.esCode.esSuccessCode, data: sequceneId });
}
});
});
}
/**
*
* @param { index, type, id }
* @version 1.0 2017-7-11 删除操作
*/
static async delES({ index, type, id }) {
let obj = Object.assign({}, { index, type, id });
return await new Promise((resolve, reject) => {
esDataSource.delete(obj, (err, data) => {
if (err) {
reject({ code: constantESCode.esCode.delFailCode, err });
} else {
resolve({ code: constantESCode.esCode.esSuccessCode, data });
}
});
});
}
/**
*
* @param { index, type, condition }
* @version 1.0 2017-7-11 更新操作
*
* 更新文档操作 局部更新 根据id进行更新
* 对于es而言,不推荐频繁更新,因为数据的一致性很难保证,更适用于搜索
*
* 常见参数如下:
* @param doc 需修改的文档体
* @param fields 指定更新完后需返回的字段
*
*/
static async updateES({ index, type, id, doc, fields, }) {
let obj = Object.assign({}, { index, type, id, body: { doc, fields, } });
return await new Promise((resolve, reject) => {
esDataSource.update(obj, (err, data) => {
if (err) {
reject({ code: constantESCode.esCode.updateFailCode, err });
} else {
resolve({ code: constantESCode.esCode.esSuccessCode, data });
}
});
});
}
/**
*获取单文档操作
*@param fields 返回指定字段 false 为禁止返回source字段 若传递数组,则指定为指定的字段名
*@version 1.0
*/
static async getDOC({ index, type, id, fields, }) {
let obj = Object.assign({}, { index, type, id, _source: fields, });
return await new Promise((resolve, reject) => {
esDataSource.get(obj, (err, data) => {
if (err) {
reject({ code: constantESCode.esCode.getDoacFailCode, err });
} else {
resolve({ code: constantESCode.esCode.esSuccessCode, data });
}
}
);
});
}
/**
* 多文档查询
* @param ids 数组id
* @version 1.0
*
*/
static async getDOCS({ index, type, ids,}) {
let obj = Object.assign({}, { index, type, body: { ids, }, });
return await new Promise((resolve, reject) => {
esDataSource.mget(obj, (err, data) => {
if (err) {
reject({ code: constantESCode.esCode.getDocsFailCode, err });
} else {
resolve({ code: constantESCode.esCode.esSuccessCode, data });
}
});
});
}
/****
*
* 批量操作语句
*常用操作 index update delete
*
*/
static async batchOperation(obj) {
return await new Promise(
(resolve, reject) => {
esDataSource.bulk({ body: obj }, (err, data) => {
if (err) {
reject({ code: constantESCode.esCode.batchFailCode, err });
} else {
resolve({ code: constantESCode.esCode.esSuccessCode, data });
}
});
}
);
}
/**
* @param { index, type,from,size, condition })
* @param from 起始位置
* @param size 分页大小
* @version 1.0 2017-7-11 查找操作
*/
static async searchES({ index, type, from, size, condition }) {
//查询记录
let obj = Object.assign({}, { index, type, from, size, body: condition });
return await new Promise((resolve, reject) => {
esDataSource.search(obj, (err, data) => {
if (err) {
reject({ code: constantESCode.esCode.searchFailCode, err });
} else {
resolve({ code: constantESCode.esCode.esSuccessCode, data });
}
});
});
}
/**
* 分页搜索(一般用于搜索大量数据使用)
* @param scroll 时间段
* @param scrollId 游标位置
* @version 1.0
*
*/
static async pageES(index, type, scroll, scrollId, condition, ) {
let obj = Object.assign({}, { index, type, scroll, scrollId, body: condition, });
return await new Promise((resolve, reject) => {
esDataSource.scroll(obj, (err, data) => {
if (err) {
reject({ code: constantESCode.esCode.searchFailCode, err });
} else {
resolve({ code: constantESCode.esCode.esSuccessCode, data });
}
});
});
}
/**
* 判断文档是否存在
*
*/
static async existEs({index,type,id}) {
return await new Promise((resolve, reject) => {
esDataSource.exists({index,type,id}, (err, data) => {
if (err) {
reject({ code: constantESCode.esCode.existDocFailCode, err });
} else {
resolve({ code: constantESCode.esCode.esSuccessCode, data });
}
});
});
}
}
module.exports = { EsUtil };
3.调用api示例
/****
* ts 实例举例
*
*/
const path = require('path');
let EsUtil = require(path.join(__dirname, '../', 'util', 'esUtil.js')).EsUtil;
/**
* 创建文档操作
*
*/
let user = {
userName: 'HH',
age: 19,
};
let isnertUser = {
index: 'test',
type: 'userInfo',
body: user,
};
/**
* 插入操作
*
*/
EsUtil.insertES(isnertUser).then(
(data) => {
if (data.code) {
console.log('插入成功');
} else {
console.log('插入失败');
}
}
);
/**
* 插入操作,带条件的
* 比如 判断用户名相同时,则不插入
* 若只判断是否存在,建议使用过滤器,这样更快,并且ES会缓存其内容
* 详情见:http://www.cnblogs.com/xing901022/p/4975931.html Query与Filter区别
*/
Object.assign(isnertUser, {
condition: {
'query': {
'bool': {
'filter': {
'term': {
'userName': 'zjx'
}
}
}
}
},
});
EsUtil.insertES(isnertUser).then(
(data) => {
if (data.code == 2) {
console.log('存在相同的数据');
} else {
console.log('插入失败');
}
}
);
/**
* 更新文档操作 局部更新 根据id进行更新 若没有字段则会自动添加
* 对于es而言,不推荐频繁更新,因为数据的一致性很难保证,更适用于搜索
*
* 常见参数如下:
* @param doc 需修改的文档体
* @param fields 指定更新完后需返回的字段
*/
let updateObj = {
index: 'test',
type: 'userInfo',
id: '32',
doc: {
userName: 'updateNamesss',
ages: 20,
},
fields: ['userName', 'age', 'ages'],
};
EsUtil.updateES(updateObj).then(
(data) => {
console.log(data.data);
}).catch(
(err) => {
console.log(err);
}
);
/**
*
* 删除操作 根据id删除
*
*/
let delObj = {
index: 'test',
type: 'userInfo',
id: 41,
};
EsUtil.delES(delObj)
.then((data) => {
console.log(data);
}).catch((err) => { console.log(err); });
/**
* 获取单个文档操作
*
*
*/
let getObj = {
index: 'test',
type: 'userInfo',
id: 22,
fields: false,
};
EsUtil.getDOC(getObj)
.then((data) => {
console.log(data);
})
.catch(
(err) => {
console.log(err);
});
/**
* mget 根据批量id查找操作
*
*
*/
let getObjs = {
index: 'test',
type: 'userInfo',
ids: [22, 23],
};
EsUtil.getDOCS(getObjs)
.then((data) => {
console.log(data);
})
.catch(
(err) => {
console.log(err);
});
/**
*
* 批量导入操作
* index update delete search
*/
let actions = Array.of(5);
actions[0] = {
index: {
_index: "test",
_type: "userInfo",
_id: 41,
},
};
actions[1] = {
'userName': 'hhh',
'age': 13,
};
actions[2] = {
update: {
_index: "test",
_type: "userInfo",
_id: 40,
},
};
actions[3] = {
'doc': {
'userName': 'hhhs',
'age': 43,
},
};
actions[4] = {
delete: {
_index: "test",
_type: "userInfo",
_id: 23,
},
};
EsUtil.batchOperation(actions).then(
(data) => {
console.log(data);
}
).catch((e) => {
console.log(e);
});
/**
* 查询操作 bool 查询 must must_not should (与或非) filtered filter 过滤器 terms term 包含语句
* 聚合函数有: aggs 中有 max min avg sum cardinality(不重复字段)
*
*
*/
//聚合举例
let searchObj = {
index: 'test',
type: 'userInfo',
from: 0,
size: 10,
condition: {
'aggs': {
'max_age': {
'max': {
'field': 'age'
}
}
},
'_source': false,//不返回文档source信息
},
from: 0,
size: 1,
};
EsUtil.searchES(searchObj)
.then((data) => { console.log(data); })
.catch((e) => { console.log(e); });
//排序举例
let sortObj = {
index: 'test',
type: 'userInfo',
from: 0,
size: 10,
condition: {
'sort': {
'age': {
'order': 'desc'
}
},
// '_source': false,//不返回文档source信息
},
// from: 0,
// size: 1,
};
EsUtil.searchES(sortObj)
.then((data) => { console.log(data); })
.catch((e) => { console.log(e); });
4.参考文章
http://www.cnblogs.com/o-andy-o/p/5067184.html 节点与集群
http://blog.csdn.net/pilihaotian/article/details/52452010 装head插件
http://www.jianshu.com/p/f437b893502a dsl 用法
http://www.cnblogs.com/xing901022/p/4930972.html nodejs 调用es 用法
http://blog.csdn.net/dm_vincent/article/details/41743955 关联语句查询
http://www.cnblogs.com/xing901022/p/5471419.html 数据类型
http://www.cnblogs.com/xing901022/p/4930972.html js 调用api