elasticsearch api与nodejs 调用实例

本文适合对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

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值