公司项目大规模使用elasticsearch,封装了统一的elasticsearchAPI,比较通用,支持多数据源和多层分组查询,可以组合类似MySQL的复杂查询
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"> <bean id="cateEsClientFactory" class="com.jd.pop.odp.util.esdb.EsClientFactory"> <constructor-arg name="clusterName" value="${pop-odp.cate.es.cluster}"/> <constructor-arg name="ips"> <value>${pop-odp.cate.es.ips}</value> </constructor-arg> <constructor-arg name="esPort" value="${pop-odp.cate.es.port}"/> </bean> <bean id="realTimeEsClientFactory" class="com.jd.pop.odp.util.esdb.EsClientFactory"> <constructor-arg name="clusterName" value="${pop-odp.realTime.es.cluster}"/> <constructor-arg name="ips"> <value>${pop-odp.realTime.es.ips}</value> </constructor-arg> <constructor-arg name="esPort" value="${pop-odp.realTime.es.port}"/> </bean> <bean id="cateEsDao" class="com.jd.pop.es.dao.cate.impl.CateEsDaoImpl"> <property name="esClientFactory" ref="cateEsClientFactory"/> </bean> <bean id="realTimeEsDao" class="com.jd.pop.es.dao.realTime.impl.RealTimeEsDaoImpl"> <property name="esClientFactory" ref="realTimeEsClientFactory"/> </bean> </beans>
import com.google.common.base.Preconditions; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; public class EsClientFactory { private static final Log logger = LogFactory.getLog(EsClientFactory.class); // 是否扫描集群 private static boolean sniff = false; // ES 集群名称 private static String clusterName; // IP地址 private static String[] ips; // 端口 private static int esPort; private TransportClient esClient;//ES 客户端对象 public EsClientFactory(String clusterName,String[] ips,int esPort) { this.clusterName=clusterName; this.ips=ips; this.esPort=esPort; init(); } /** * ES 客户端连接初始化 * * @return ES客户端对象 */ private void init() { Preconditions.checkNotNull(clusterName, "es 服务clusterName未配置"); Preconditions.checkNotNull(ips, "es 服务ip未配置"); Preconditions.checkArgument(esPort > 0, "es 服务服务port未配置"); //设置集群的名字 Settings settings = ImmutableSettings.settingsBuilder() .put("cluster.name", clusterName) .put("client.transport.sniff", sniff) .build(); //创建集群client并添加集群节点地址 esClient = new TransportClient(settings); for (String ip : ips) { esClient.addTransportAddress(new InetSocketTransportAddress(ip, esPort)); } } public TransportClient getEsClient() { return esClient; } public boolean isSniff() { return sniff; } public String getClusterName() { return clusterName; } public String[] getIps() { return ips; } public int getEsPort() { return esPort; } }
public class CateEsDaoImpl extends EsDbUtils implements CateEsDao { @Override public List<CateVenderData> queryListByFilterQuery(EsQueryObj esQueryObj) throws Exception { return (List<CateVenderData>)queryObjectListByFilterQuery(esQueryObj,CateVenderData.class); } @Override public List<CateVenderData> queryListByFilterQueryWithAgg(EsQueryObj esQueryObj) throws Exception { return (List<CateVenderData>)queryObjectListByFilterQueryWithAgg(esQueryObj,CateVenderData.class); } } public class RealTimeEsDaoImpl extends EsDbUtils implements RealTimeEsDao { @Override public List<OdpOperatorSum> queryListByFilterQuery(EsQueryObj esQueryObj) throws Exception { return (List<OdpOperatorSum>)queryObjectListByFilterQuery(esQueryObj,OdpOperatorSum.class); } @Override public List<OdpOperatorSum> queryListByFilterQueryWithAgg(EsQueryObj esQueryObj) throws Exception { return (List<OdpOperatorSum>)queryObjectListByFilterQueryWithAgg(esQueryObj,OdpOperatorSum.class); } }
import com.google.gson.Gson; import org.apache.commons.beanutils.PropertyUtils; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchType; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.aggregations.Aggregation; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder; import org.elasticsearch.search.aggregations.metrics.avg.Avg; import org.elasticsearch.search.aggregations.metrics.sum.Sum; import org.elasticsearch.search.sort.SortOrder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.*; /** * Created with IntelliJ IDEA. * User: supeidong * Date: 2016/3/16 * Time: 13:37 * To change this template use File | Settings | File Templates. */ public class EsDbUtils <T>{ private static final Logger logger = LoggerFactory.getLogger(EsDbUtils.class); private static final int FromIndex = 0; private static final int MinSize = 100; private static final int MaxSize = 100000; private static final int GroupMinSize = 100; private static final int GroupMaxSize = 500; private EsClientFactory esClientFactory;//ES 客户端工厂类 /** * 根据过滤条件查询出数据列表.需要传递索引和表名 * @param esQueryObj ES查询对象 * @param targetClass ES结果需要转换的类型 * @return */ public List<? extends Object> queryObjectListByFilterQuery(EsQueryObj esQueryObj,Class targetClass) throws Exception { validationEsQuery(esQueryObj); List<Object> esRecords = new ArrayList<Object>(); long startCountTime = System.currentTimeMillis(); //创建ES查询Request对象 SearchRequestBuilder esSearch= esClientFactory.getEsClient().prepareSearch(esQueryObj.getIndexName()); esSearch.setTypes(esQueryObj.getTypeName()) .setSearchType(SearchType.QUERY_THEN_FETCH) .setFrom((esQueryObj.getFromIndex() > 0) ? esQueryObj.getFromIndex() : FromIndex) .setSize((0 <esQueryObj.getSize() && esQueryObj.getSize() <= MaxSize) ? esQueryObj.getSize() : MinSize); //添加查询条件 if(esQueryObj.getAndFilterBuilder()!=null){ esSearch.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), esQueryObj.getAndFilterBuilder())); } //添加多级排序 if(esQueryObj.getSortField()!=null) { for (Map.Entry<String, SortOrder> entry : esQueryObj.getSortField().entrySet()) { esSearch.addSort(entry.getKey(), entry.getValue()); } } //执行查询 SearchResponse response =esSearch .execute().actionGet(); for (SearchHit hit : response.getHits()) { Object t = mapResult(hit.sourceAsMap(), targetClass); esRecords.add(t); } logger.info("queryObjectListByFilterQuery search " + response.getHits().getTotalHits() + " data ,esQueryObj=" + new Gson().toJson(esQueryObj)+"-----------------------------------------! use " + (System.currentTimeMillis() - startCountTime) + " ms."); return esRecords; } /** * 根据过滤条件和分组键SUM/AVG键获取分组结果(目前分组结果不支持LIMIT操作) * @param esQueryObj ES查询对象 * @param targetClass ES结果需要转换的类型 * @return * @throws Exception */ public List<? extends Object> queryObjectListByFilterQueryWithAgg(EsQueryObj esQueryObj,Class targetClass) throws Exception { validationEsGroupQuery(esQueryObj); List<Object> esRecords = new ArrayList<Object>(); long startCountTime = System.currentTimeMillis(); if( esQueryObj.getSumFields()==null){ esQueryObj.setSumFields(new ArrayList<String>()); } if(esQueryObj.getAvgFields()==null){ esQueryObj.setAvgFields(new ArrayList<String>()); } TermsBuilder agg = getEsAgg(esQueryObj); //创建ES查询Request对象 SearchRequestBuilder esSearch= esClientFactory.getEsClient().prepareSearch(esQueryObj.getIndexName()); esSearch.setTypes(esQueryObj.getTypeName()) .setSearchType(SearchType.QUERY_THEN_FETCH) .addAggregation(agg); //添加查询条件 if(esQueryObj.getAndFilterBuilder()!=null){ esSearch.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), esQueryObj.getAndFilterBuilder())); } //添加多级排序 if(esQueryObj.getSortField()!=null) { for (Map.Entry<String, SortOrder> entry : esQueryObj.getSortField().entrySet()) { esSearch.addSort(entry.getKey(), entry.getValue()); } } //执行查询 SearchResponse response =esSearch .execute().actionGet(); List<Map<String, Object>> aggMaps= getAggMap(response,esQueryObj.getGroupFields(), esQueryObj.getSumFields(), esQueryObj.getAvgFields()); for(Map<String, Object> aggMap : aggMaps){ Object t = mapResult(aggMap, targetClass); esRecords.add(t); } logger.info("queryObjectListByFilterQuery search " + response.getHits().getTotalHits() + " data,esQueryObj=" + new Gson().toJson(esQueryObj)+"-----------------------------------------! use " + (System.currentTimeMillis() - startCountTime) + " ms."); return esRecords; } /** * 根据分组键和SUM/AVG键组合AGG条件 * @param esQueryObj * @return */ private TermsBuilder getEsAgg(EsQueryObj esQueryObj) throws Exception{ List<String> groupFields= esQueryObj.getGroupFields(); List<String> sumFields= esQueryObj.getSumFields(); List<String> avgFields= esQueryObj.getAvgFields(); int groupSize=esQueryObj.getGroupSize(); Map<String, SortOrder> groupSortMap=esQueryObj.getGroupSortField(); TermsBuilder termsBuilder = AggregationBuilders.terms(groupFields.get(0)).field(groupFields.get(0)); if (groupFields.size() == 1) { //设置排序后最后一层的结果数目 termsBuilder.size((0 <groupSize && groupSize <= GroupMaxSize) ? groupSize : GroupMinSize); //添加group排序字段 if(groupSortMap!=null) { List<Terms.Order> termsOrders=new ArrayList<Terms.Order>(); for (Map.Entry<String, SortOrder> entry : groupSortMap.entrySet()) { if(entry.getValue().equals(SortOrder.ASC)){ termsOrders.add(Terms.Order.aggregation(entry.getKey(),true)); }else{ termsOrders.add(Terms.Order.aggregation(entry.getKey(), false)); } } termsBuilder.order(Terms.Order.compound(termsOrders)); } for (String avgField : avgFields) { termsBuilder.subAggregation(AggregationBuilders.avg(avgField).field(avgField)); } for (String sumField : sumFields) { termsBuilder.subAggregation(AggregationBuilders.sum(sumField).field(sumField)); } } else { termsBuilder.subAggregation(getChildTermsBuilder(groupFields, 1, sumFields, avgFields,groupSize,groupSortMap)); //设置最外层分组量 termsBuilder.size(GroupMaxSize); } return termsBuilder; } /** * 通过递归的方式获取bucket agg分组语句 * @param groupFields * @param i * @param sumFields * @param avgFields * @return */ private TermsBuilder getChildTermsBuilder(List<String> groupFields,int i,List<String> sumFields, List<String> avgFields,int groupSize,Map<String, SortOrder> groupSortMap){ if(i+1==groupFields.size()){ TermsBuilder termsBuilderLast = AggregationBuilders.terms(groupFields.get(i)).field(groupFields.get(i)); //设置排序后最后一层的结果数目 termsBuilderLast.size((0 <groupSize && groupSize <= GroupMaxSize) ? groupSize : GroupMinSize); //添加group排序字段 if(groupSortMap!=null) { for (Map.Entry<String, SortOrder> entry : groupSortMap.entrySet()) { if(entry.getValue().equals(SortOrder.ASC)){ termsBuilderLast.order(Terms.Order.aggregation(entry.getKey(),true)); }else{ termsBuilderLast.order(Terms.Order.aggregation(entry.getKey(),false)); } } } for (String avgField : avgFields) { termsBuilderLast.subAggregation(AggregationBuilders.avg(avgField).field(avgField)); } for (String sumField : sumFields) { termsBuilderLast.subAggregation(AggregationBuilders.sum(sumField).field(sumField)); } return termsBuilderLast; } else{ TermsBuilder termsBuilder= AggregationBuilders.terms(groupFields.get(i)).field(groupFields.get(i)); //设置最外层分组量 termsBuilder.size(GroupMaxSize); return termsBuilder.subAggregation(getChildTermsBuilder(groupFields,i+1,sumFields,avgFields,groupSize,groupSortMap)); } } /** * 根据汇总键和SUM/AVG键,组合返回的查询值为MAP格式 * @param response * @param groupFields * @param sumFields * @param avgFields * @return */ private List<Map<String, Object>> getAggMap(SearchResponse response,List <String>groupFields,List<String> sumFields, List<String> avgFields){ List<Map<String, Object>> aggMaps = new ArrayList<Map<String, Object>>(); //首先获取最外层的AGG结果 Terms tempAggregation = response.getAggregations().get(groupFields.get(0)); //只有一个分组键不用进行递归 if(groupFields.size()==1){ for(Terms.Bucket tempBk:tempAggregation.getBuckets()){ Map<String, Object> tempMap = new HashMap<String, Object>(); tempMap.put(tempAggregation.getName(), tempBk.getKey()); for (Map.Entry<String, Aggregation> entry : tempBk.getAggregations().getAsMap().entrySet()) { String key = entry.getKey(); if (sumFields.contains(key)) { Sum aggSum = (Sum) entry.getValue(); double value = aggSum.getValue(); tempMap.put(key, value); } if (avgFields.contains(key)) { Avg aggAvg = (Avg) entry.getValue(); double value = aggAvg.getValue(); tempMap.put(key, value); } } aggMaps.add(tempMap); } } else { for (Terms.Bucket bk : tempAggregation.getBuckets()) { //每个最外层的分组键生成一个键值对MAP Map<String, Object> nkMap = new HashMap<String, Object>(); nkMap.put(tempAggregation.getName(), bk.getKey()); //通过递归的方式填充键值对MAP并加到最终的列表中 getChildAggMap(bk, 1, groupFields, sumFields, avgFields, nkMap, aggMaps); } } return aggMaps; } /** * 深层递归所有的AGG返回值,组合成最终的MAP列表 * @param bk 每次递归的单个Bucket * @param i 控制分组键列表到了哪一层 * @param groupFields 分组键列表 * @param sumFields SUM键列表 * @param avgFields AVG键列表 * @param nkMap 键值对MAP * @param aggMaps 最终结果的中间值 * @return */ private List<Map<String, Object>> getChildAggMap(Terms.Bucket bk,int i,List <String>groupFields,List<String> sumFields, List<String> avgFields,Map<String, Object> nkMap,List<Map<String, Object>> aggMaps){ if(i==groupFields.size()-1){ Terms tempAggregation = bk.getAggregations().get(groupFields.get(i)); for(Terms.Bucket tempBk:tempAggregation.getBuckets()){ Map<String, Object> tempMap = new HashMap<String, Object>(); tempMap.putAll(nkMap); tempMap.put(tempAggregation.getName(), tempBk.getKey()); for (Map.Entry<String, Aggregation> entry : tempBk.getAggregations().getAsMap().entrySet()) { String key = entry.getKey(); if (sumFields.contains(key)) { Sum aggSum = (Sum) entry.getValue(); double value = aggSum.getValue(); tempMap.put(key, value); } if (avgFields.contains(key)) { Avg aggAvg = (Avg) entry.getValue(); double value = aggAvg.getValue(); tempMap.put(key, value); } } aggMaps.add(tempMap); } return aggMaps; } else{ Terms tempAggregation = bk.getAggregations().get(groupFields.get(i)); for(Terms.Bucket tempBk:tempAggregation.getBuckets()){ nkMap.put(tempAggregation.getName(), tempBk.getKey()); getChildAggMap(tempBk, i + 1, groupFields, sumFields, avgFields, nkMap, aggMaps); } return aggMaps; } } /** * 将ES结果映射到指定对象 * @param resultMap * @param cls * @return * @throws Exception */ public T mapResult(Map<String, Object> resultMap, Class<T> cls) throws Exception{ T result = cls.newInstance(); Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { Object object = resultMap.get(field.getName()); if (object != null) { //根据几种基本类型做转换 if (field.getType().equals(Long.class) || field.getType().equals(long.class)) { if(object.toString().indexOf('.')>0){ PropertyUtils.setProperty(result, field.getName(), Long.parseLong(object.toString().substring(0, object.toString().indexOf('.')))); }else{ PropertyUtils.setProperty(result, field.getName(), Long.parseLong(object.toString())); } }else if (field.getType().equals(long.class) || field.getType().equals(long.class)) { if(object.toString().indexOf('.')>0){ PropertyUtils.setProperty(result, field.getName(), Long.parseLong(object.toString().substring(0, object.toString().indexOf('.')))); }else{ PropertyUtils.setProperty(result, field.getName(), Long.parseLong(object.toString())); } }else if (field.getType().equals(Integer.class) || field.getType().equals(Integer.class)) { if(object.toString().indexOf('.')>0){ PropertyUtils.setProperty(result, field.getName(), Integer.parseInt(object.toString().substring(0, object.toString().indexOf('.')))); }else{ PropertyUtils.setProperty(result, field.getName(), Integer.parseInt(object.toString())); } }else if (field.getType().equals(int.class) || field.getType().equals(int.class)) { if(object.toString().indexOf('.')>0){ PropertyUtils.setProperty(result, field.getName(), Integer.parseInt(object.toString().substring(0, object.toString().indexOf('.')))); }else{ PropertyUtils.setProperty(result, field.getName(), Integer.parseInt(object.toString())); } }else if (field.getType().equals(BigDecimal.class) || field.getType().equals(BigDecimal.class)) { PropertyUtils.setProperty(result, field.getName(), BigDecimal.valueOf(Double.parseDouble(object.toString()))); }else if (field.getType().equals(Double.class) || field.getType().equals(Double.class)) { PropertyUtils.setProperty(result, field.getName(), Double.parseDouble(object.toString())); }else if (field.getType().equals(double.class) || field.getType().equals(double.class)) { PropertyUtils.setProperty(result, field.getName(), Double.parseDouble(object.toString())); }else if (field.getType().equals(Date.class) || field.getType().equals(Date.class)) { PropertyUtils.setProperty(result, field.getName(), DateUtil.createDate(object.toString())); }else if (field.getType().equals(String.class) || field.getType().equals(String.class)) { PropertyUtils.setProperty(result, field.getName(), object); } } } return result; } /** * 验证ES查询对象 * @param esQueryObj * @throws Exception */ private void validationEsQuery(EsQueryObj esQueryObj) throws Exception{ if(StringUtils.isEmpty(esQueryObj.getIndexName())&&StringUtils.isEmpty(esQueryObj.getTypeName())){ throw new Exception("please check indexName and typeName"); } } /** * 验证ES查询分组对象 * @param esQueryObj * @throws Exception */ private void validationEsGroupQuery(EsQueryObj esQueryObj) throws Exception{ if(StringUtils.isEmpty(esQueryObj.getIndexName())&&StringUtils.isEmpty(esQueryObj.getTypeName())){ throw new Exception("please check indexName and typeName"); } boolean groupOrderStatus=true; st:for (Map.Entry<String, SortOrder> entry : esQueryObj.getGroupSortField().entrySet()) { if(!esQueryObj.getSumFields().contains(entry.getKey())&&!esQueryObj.getAvgFields().contains(entry.getKey())){ groupOrderStatus=false; break st; } } if(!groupOrderStatus){ throw new Exception("please check groupSortField"); } if (esQueryObj.getGroupFields().isEmpty() || esQueryObj.getGroupFields().size() <= 0 ||(esQueryObj.getSumFields().isEmpty()&&esQueryObj.getAvgFields().isEmpty())) { throw new Exception("please check groupFields and sumFields and avgFields"); } } public EsClientFactory getEsClientFactory() { return esClientFactory; } public void setEsClientFactory(EsClientFactory esClientFactory) { this.esClientFactory = esClientFactory; } }
import org.elasticsearch.index.query.AndFilterBuilder; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.search.sort.SortOrder; import java.util.List; import java.util.Map; public class EsQueryObj { /** * ES索引名 */ String indexName; /** * ES TYPE名(表名) */ String typeName; /** * 查询条件组合,类似于 "boolQuery().must( QueryBuilders.termQuery("opTime", "2016-03-30")).must(QueryBuilders.termQuery("operErpID", "xingkai"))" */ BoolQueryBuilder bq; /** * 查询条件组合,类似于 "boolQuery().must( QueryBuilders.termQuery("opTime", "2016-03-30")).must(QueryBuilders.termQuery("operErpID", "xingkai"))" */ AndFilterBuilder andFilterBuilder; /** * 分组键值列表,类似于group by 之后的字段 */ List <String> groupFields; /** * 分组SUM键值列表 */ List <String> sumFields; /** * 分组AVG键值列表 */ List <String> avgFields; /** * 排序字段键值对,可以添加多个,类似于("opTime","DESC") */ Map<String,SortOrder> sortField; /** * 分组后排序字段键值对,可以添加多个,类似于("opTime","DESC"),注意此处最后PUT的键最先排序,排序键必须在sumFields或avgFields(只针对最后一层分组) */ Map<String,SortOrder> groupSortField; /** * 分组后返回数据数量,默认为100,最大不能超过500(只针对最后一层分组) */ int groupSize; /** * 取值的起始位置,默认为0 */ int fromIndex; /** * 返回数据数量,默认为100,最大不能超过100000 */ int size; public String getIndexName() { return indexName; } public void setIndexName(String indexName) { this.indexName = indexName; } public String getTypeName() { return typeName; } public void setTypeName(String typeName) { this.typeName = typeName; } public BoolQueryBuilder getBq() { return bq; } public void setBq(BoolQueryBuilder bq) { this.bq = bq; } public AndFilterBuilder getAndFilterBuilder() { return andFilterBuilder; } public void setAndFilterBuilder(AndFilterBuilder andFilterBuilder) { this.andFilterBuilder = andFilterBuilder; } public List<String> getGroupFields() { return groupFields; } public void setGroupFields(List<String> groupFields) { this.groupFields = groupFields; } public List<String> getSumFields() { return sumFields; } public void setSumFields(List<String> sumFields) { this.sumFields = sumFields; } public List<String> getAvgFields() { return avgFields; } public void setAvgFields(List<String> avgFields) { this.avgFields = avgFields; } public Map<String, SortOrder> getSortField() { return sortField; } public void setSortField(Map<String, SortOrder> sortField) { this.sortField = sortField; } public int getFromIndex() { return fromIndex; } public void setFromIndex(int fromIndex) { this.fromIndex = fromIndex; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public Map<String, SortOrder> getGroupSortField() { return groupSortField; } public void setGroupSortField(Map<String, SortOrder> groupSortField) { this.groupSortField = groupSortField; } public int getGroupSize() { return groupSize; } public void setGroupSize(int groupSize) { this.groupSize = groupSize; } }
相关推荐
ElasticSearch(基本操作和高级查询)、Async(异步任务)、集成Dubbo(采用官方的starter)、MongoDB(文档数据库)、neo4j(图数据库)、docker(容器化)、JPA多数据源、Mybatis多数据源、代码生成器、GrayLog(日志收集)、...
实现功能 ...$ npm install babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-helper-vue-jsx-merge-props babel-preset-es2015 --save-dev $ npm --registry https://registry.npm.taoba
ElasticSearch(`基本操作和高级查询`)、Async(`异步任务`)、集成Dubbo(`采用官方的starter`)、MongoDB(`文档数据库`)、neo4j(`图数据库`)、docker(`容器化`)、`JPA多数据源`、`Mybatis多数据源`、`代码生成器`、Gray...
使用MetaModel,您可以使用统一的连接器和查询API来访问许多非常不同... 相反,我们强调元数据的抽象和在运行时添加数据源的能力,从而使MetaModel非常适合通用数据处理应用程序,而不适用于围绕特定域建模的应用程序。...
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
城市旅游产业的日新月异影响着村镇旅游产业的发展变化。网络、电子科技的迅猛前进同样牵动着旅游产业的快速成长。随着人们消费理念的不断发展变化,越来越多的人开始注意精神文明的追求,而不仅仅只是在意物质消费的提高。塞北村镇旅游网站的设计就是帮助村镇发展旅游产业,达到宣传效果,带动一方经济发展。而在线消费与查询正在以高效,方便,时尚等的特点成为广大互联网用户的首选。塞北村镇旅游网站设计与开发以方便、快捷、费用低的优点正慢慢地进入人们的生活。人们从传统的旅游方式转变为在线预览,减轻了劳动者的工作量。使得旅游从业人员有更多时间来获取、了解、掌握信息。 塞北村镇旅游网站根据当地旅游风景和特色的实际情况,设计出一套适合当地旅游信息网站,通过网络,实现该网站的推广从而达到宣传的效果。 本系统在设计方面采用JSP和Java语言以及html脚本语言,同时采用B/S模式,进行各个界面和每个功能的设计与实现,后台管理与设计选用了SQL Server 2005数据库,前台设计与后台管理相结合,共同完成各功能模块的功能。
JSP考试系统_jspks.rar是一个为计算机专业学生和教师设计的JSP源码资料包,它提供了一个全面的、易于使用的在线考试平台。这个系统是基于Java Server Pages (JSP)技术构建的,这是一种用于创建动态网页的服务器端技术。通过这个系统,用户可以创建、管理和参加在线考试。这个系统的主要功能包括:用户注册和登录,试题管理(包括添加、修改和删除试题),试卷管理(包括创建、编辑和删除试卷),考试管理(包括开始、暂停和结束考试),成绩管理(包括查看和统计成绩)等。此外,系统还提供了丰富的试题类型,如选择题、填空题、判断题和简答题等,以满足不同的考试需求。JSP考试系统的界面设计简洁明了,操作方便,无论是教师还是学生都可以轻松上手。对于教师来说,他们可以通过这个系统轻松地管理试题和试卷,节省了大量的时间和精力。对于学生来说,他们可以随时随地参加在线考试,方便快捷。总的来说,JSP考试系统_jspks.rar是一个非常实用的JSP源码资料包,它不仅可以帮助学生更好地学习和掌握JSP技术,也可以帮助教师更有效地管理在线考试。无论是对于学生还是教师,这个系统都是一个不可或缺的工具。重
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
词向量
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
基于matlab开发的光谱数据预处理程序,包括MSC,SNV,归一化,中心化,导数等等.rar
优秀源码设计,详情请查看资源源码内容
基于matlab开发的TD-LTE随机接入过程前导序列检测算法Matlab信道仿真.rar
词向量 词向量(Word Vectors)是一种用来表示词语语义和语法信息的数学模型。它将词语转换为固定长度的实数向量,使得词向量之间的距离(通常使用余弦相似度)可以反映出词语之间的语义关系。词向量在自然语言处理和机器学习领域有广泛的应用,例如文本分类、情感分析、句子相似度计算等。 词向量的发展经历了从传统的one-hot表示到分布式表示的转变。传统的one-hot表示将每个词语表示为一个高维稀疏的向量,向量中只有一个元素为1,其余元素都为0,表示词语在词汇表中的位置。然而,这种表示方式无法准确捕捉词语之间的语义关系。 为了解决这个问题,分布式表示方法被提出。分布式表示将每个词语表示为一个低维稠密的实数向量,其中每个元素都包含了词语的语义和语法信息。这种表示方式的关键思想是,具有相似语义和上下文的词语在向量空间中更加接近。 现在广泛应用的词向量模型有许多种,其中最著名的是Word2Vec模型和GloVe模型。Word2Vec是一种基于神经网络的模型,它通过一种称为连续词袋(CBOW)和另一种称为跳字(Skip-gram)的训练方法来学习词向量。GloVe模型是一种基于全局词频的词
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
超市会员积分管理系统主要用于实现了企业管理数据统计等。本系统结构如下: (1)网络会员管理中心界面: 会员修改密码信息模块:实现会员密码功能; 会员登陆模块:实现会员登陆功能; 会员注册模块:实现会员注册功能; 留言板模块:实现留言板留言功能 (2)后台管理界面: 系统用户管理模块:实现管理员的增加、查看功能; 会员信息管理模块:实现会员信息的增加、修改、查看功能; 注册用户管理模块:实现注册用户的增加、修改、查看功能; 会员卡管理模块:实现会员卡信息的增加、查看功能; 商品销售管理模块:实现商品信息的增加、查看功能; 会员积分管理模块:实现合作公司信息的增加、查看功能; 信息统计模块:实现数据统计报表功能; 留言板模块:实现留言板信息的增加、修改、查看功能;
信息办公XML考试系统_xmlks.rar是一款专为计算机专业设计的JSP源码资料包。这个资料包包含了丰富的功能和特性,旨在为教育机构、培训中心和企业提供一个完整的在线考试解决方案。通过使用这个资料包,用户可以轻松地创建和管理自己的在线考试平台,实现对学员的考试、评分和成绩管理。首先,这个资料包采用了流行的JSP技术,结合了XML数据存储和处理,使得系统具有很高的可扩展性和灵活性。用户可以方便地根据自己的需求定制和修改系统的功能和界面。同时,系统还支持多种题型,如选择题、填空题、判断题等,满足不同类型考试的需求。其次,信息办公XML考试系统_xmlks.rar具有良好的用户体验和易用性。系统的界面设计简洁明了,操作流程清晰易懂,使得考生可以快速上手并完成考试。同时,系统还提供了丰富的帮助文档和教程,方便用户在使用过程中随时查阅和学习。此外,这个资料包还具有强大的后台管理功能。管理员可以轻松地添加、删除和修改试题,设置考试参数,查看考生的成绩和答题情况。同时,系统还支持多种权限管理,确保数据的安全性和保密性。总之,信息办公XML考试系统_xmlks.rar是一款功能强大、易用性高、可扩展
该资源包“130222.rar”是一个针对计算机专业学生或开发者设计的基于Java服务器页面(JSP)、Servlet以及MySQL数据库的博客系统网站的源码资料。这个压缩文件包含了构建一个功能齐全的动态网站所需的全部源代码和相关文档,它允许用户通过互联网发布文章、分享观点,并与他人进行互动。在内容上,它可能包含了多个JSP页面文件,用于展示博客首页、文章列表、文章内容页、写文章的表单等界面;包含了Servlet类文件,用于处理用户的请求、与数据库交互以及业务逻辑的处理;还可能包含配置文件如web.xml,用于配置Servlet映射等。至于数据库部分,则包括了MySQL的数据库文件,其中存储了博客系统的数据结构、初始数据以及存储过程等。此资料包是一套学习和实践Web开发的好材料,尤其适合那些想要深入学习JSP、Servlet和数据库交互技术的学习者。通过分析和运行这些源码,学习者可以了解Web应用的开发流程,掌握如何在Java Web环境中使用MVC设计模式,以及如何实现用户身份验证、会话管理、数据持久化等关键功能。由于是基于JSP的传统Web开发技术,虽然现代Web开发领域已逐渐向全
可视化图库Pandas_Alive实现动态图表绘制,使用时减少数据会使生成GIF的时间变短。通过对CSV文件分析,实现动态条形图、动态曲线图、气泡图、饼状图、地理空间图等多个动态图表的可视化分析。
基于SSM的“停车场管理系统”的设计与实现基于SSM的“停车场管理系统”的设计与实现基于SSM的“停车场管理系统”的设计与实现基于SSM的“停车场管理系统”的设计与实现基于SSM的“停车场管理系统”的设计与实现基于SSM的“停车场管理系统”的设计与实现基于SSM的“停车场管理系统”的设计与实现基于SSM的“停车场管理系统”的设计与实现基于SSM的“停车场管理系统”的设计与实现