• Elasticsearch基本命令


    curl命令

    -XGET一种请求方法

    -d 标识以post形式传入参数 ,写在请求正文里面

    ?pretty=true 以格式的形式显示结果

    curl -XGET http://localhost:9200/_cluster/health?pretty --查询elasticsearch的健康信息
    curl -XGET http://localhost:9200/ --查询实例的相关信息
    curl -XGET http://localhost:9200/_cluster/nodes/ --得到集群中节点的相关信息
    curl -XPOST http://localhost:9200/_cluster/nodes/_shutdown --关闭整个集群
    curl -XPOST http://localhost:9200/_cluster/nodes/aaaa/_shutdown --关闭集群中指定节点
    curl -XPOST http://localhost:9200/lishuai --创建名为lishuai的索引
    curl -XDELETE http://localhost:9200/lishuai --删除名为lishuai的索引

    curl -XGET  'http://10.10.110.2:19200/benlaitest/_search?pretty=true' -d '{"query":{"multi_match":{"query":"法国","fields":["firstname","lastname"]}}}'   --查询数据(匹配firstname和lastname)

    curl http://10.10.110.160:9200/benlaitest/_analyze?analyzer=standard -d 我爱你中国

    postman执行请求API:

    http://10.10.110.160:9200/_cat/indices?v      -- Get请求 查看有多少索引

    http://10.10.110.160:9200/benlaitest/_analyze?analyzer=standard  --查看分词结果

     

    {
      "tokens": [
        {
          "token": "",
          "start_offset": 0,
          "end_offset": 1,
          "type": "<IDEOGRAPHIC>",
          "position": 0
        },
        {
          "token": "",
          "start_offset": 1,
          "end_offset": 2,
          "type": "<IDEOGRAPHIC>",
          "position": 1
        },
        {
          "token": "",
          "start_offset": 2,
          "end_offset": 3,
          "type": "<IDEOGRAPHIC>",
          "position": 2
        },
        {
          "token": "",
          "start_offset": 3,
          "end_offset": 4,
          "type": "<IDEOGRAPHIC>",
          "position": 3
        },
        {
          "token": "",
          "start_offset": 4,
          "end_offset": 5,
          "type": "<IDEOGRAPHIC>",
          "position": 4
        },
        {
          "token": "",
          "start_offset": 5,
          "end_offset": 6,
          "type": "<IDEOGRAPHIC>",
          "position": 5
        },
        {
          "token": "",
          "start_offset": 6,
          "end_offset": 7,
          "type": "<IDEOGRAPHIC>",
          "position": 6
        }
      ]
    }
    View Code

    一 DSL查询命令 -基本查询

    1. term 匹配指定的文档单元(匹配的是分词后的词条,假如川普分词后为 川和普,那么term匹配川普是无结果的,要用term匹配'川'或者'普'),1 至少匹配1个 2匹配两个:
      {"terms":{"tag":["a","b"],"mininmum":1}} 
    2. match 根据不同的字段选择合适的分析器,一个很智能的查询器,可以通过指定他的参数来控制匹配行文 operator 控制关联的查询条件 and或者or:
      {"query":{match{"title":{"query":"a b }c","operation":"and"}}}
    3. multi_match 与match查询类似,不同的是它可以作用在多个字段上:
      {"query":{"multi_match":{"query":"a v b","fields":["title","content"]}}}
    4. query_string 查询 支持lucene的查询语法:
      {"query":{"query_string":{"query":"titlename:你好^10 +titlename:哈哈","default_field":"titlename"}}}
      {"query":{"query_string":{"query":"你好 中国","fields":["title","name"],"use_dis_max":true}}}
    5. range查询 只针对单个字段
      {"query":{"range":{"year":{"from":1700,"to":1900}}}}

    bool查询,复合查询,可以将无限数目的查询封装在一起

    {"query":{"bool":{"must":{"term":{"title":"中国"}},"should":{"term":{"name":""}}}}}

    其他查询方式:

    1. boosting查询 两个查询封装一起的查询
    2. constant_score 恒定分值查询
    3. indices 针对多个索引进行查询
    4. custom_filter_score custom_boost_factor custom_score
    5.  ids
      {
        "query": {
          "ids": {
            "type": "product",
            "values": [
              "0001-2020774",
              "0001-2020775"
            ]
          }
        }
      }
      View Code
    6.  prefix 前缀查询
    7. 模糊查询
    8.  fuzzy 查询 相似度查询,消耗cpu
    9.  fuzzy_like_zhis 基于模糊串
    10.  fuzzy_like_zhis_field
    11.  more_like_this 
    12.  mroe_like_this_field
    13.  match_all 匹配所有文档
    14.  wildcard 查询 通配符查询

    二  DSL查询命令 - 范围查询和排序

    1   index/product/_search  查询6到11块的商品 

    {
      "query": {
        "range": {
          "price": {
            "gte": "6",
            "lte": "11"
          }
        }
      }
    }
    View Code

    2    查询0-11块之间的商品,先按照相关性得分降序排列,然后按照价格升序

    {
      "query": {
        "range": {
          "price": {
            "gte": "0",
            "lte": "11"
          }
        }
      },
      "sort": [
        {
          "_score": "desc"
        },
        {
          "price": "asc"
        }
      ]
    }
    View Code

    结果: 

     三:DSL查询命令 - 过滤器

    1)过滤器会先执行查询,然后再对查询文档进行过滤

    {
      "query": {
        "field": {
          "title": "中国"
        },
        "filter": {
          "term": {
            "year": 1949
          }
        }
      }
    }
    View Code

    但是先执行过滤,然后对过滤结果进行查询。效率更高:

    {
      "filter": {
        "range": {
          "year": {
            "from": 1700,
            "to": 1900
          }
        }
      }
    }
    
    {
      "query": {
        "filtered": {
          "field": {
            "title": "中国"
          },
          "filter": {
            "term": {
              "year": 1949
            }
          }
        }
      }
    }
    View Code

    2)exists过滤器 只过滤有指定字段的文档 相反的 missing

    3)script 脚本过滤 ,过滤得到100年以前的文档:

    {
      "filter": {
        "script": {
          "script": "now - doc['year'].value>100",
          "params": {
            "now": 2016
          }
        }
      }
    }
    View Code

     四:DSL查询命令 - 聚合

    AGGS

     1)针对性别进行分组:

    {
      "size": 0,
      "aggs": {
        "agg_sex": {
          "terms": {
            "field": "gender"
          }
        }
      }
    }
    View Code

    结果:

    {
      "took": 24,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 6,
        "max_score": 0,
        "hits": [
     
        ]
      },
      "aggregations": {
        "agg_sex": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": 1,
              "key_as_string": "true",
              "doc_count": 4
            },
            {
              "key": 0,
              "key_as_string": "false",
              "doc_count": 2
            }
          ]
        }
      }
    }
    View Code

    2)得到最大价格:

    {
      "size": 0,
      "aggs": {
        "agg_price": {
          "max": {
            "field": "price"
          }
        }
      }
    }
    View Code

    结果:

    {
      "took": 16,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 6,
        "max_score": 0,
        "hits": [
     
        ]
      },
      "aggregations": {
        "agg_price": {
          "value": 20.36
        }
      }
    }
    View Code

    另外还有:  min,max,sum,avg    range,postfilter解决了仅仅过滤搜索结果,但是并不影响聚合结果

     五:DSL查询命令 - 统计

    faceting 

    1)query统计:

    {"query":{"match_all":{}},"facets":{"my_query_facet":{"query":{"term":{"tags":"person"}}}}}

    2)filter统计:my_filter_facet

    3)terms统计:返回指定字段中使用最多的词项

    4)range统计 :ranges_facet_result 统计指定范围的文档数。选取不同的字段进行数据聚合计算,使用 key_field和key_value 前者指定应该对哪个字段取值检查是否属于指定范围,后者指明 
    应该对那些字段进行聚合计算

    5)statistical统计:是的我们可以对一个数值型字段计算统计,得到个数综合平方和均值最小值最大值

    {"query":{"match_all":{}},"facets":{"statistical_test":{"statistical":{"field":"price"}}}}

    6)terms_stats 统计,过滤统计结果:facet_filter

    六:mapping嵌套

    mapping:{
      "mappings": {
        "test": {
          "properties": {
            "productname": {
              "type": "string"
            },
    
            "category": {
              "type": "nested",
              "properties": {
    
                "category1Sysno": {
                  "type": "string",
                  "index": "not_analyzed"
                },
                "category2Sysno": {
                  "type": "string",
                  "index": "not_analyzed"
                },
                "category3Sysno": {
                  "type": "string",
                  "index": "not_analyzed"
                },
                "category1Souce": {
                  "type": "int",
                  "index": "not_analyzed"
                },
                "category2Souce": {
                  "type": "int",
                  "index": "not_analyzed"
                },
                "category3Souce": {
                  "type": "int",
                  "index": "not_analyzed"
                }
    
              }
            }
          }
        }
      }
    }
    
    //DSL 查询
    {
      "query": {
        "nested": {
          "path": "category",
          "query": {
            "bool": {
              "must": [
                {
                  "term": {
                    "category.category1Sysno": "1"
                  }
                }
              ]
            }
          }
        }
      }
    }
    
    //注意:在嵌套和父子中,不能根据子文档field进行排序;例如此例中根据category.category1Souce对搜索结果进行排序;
    //使用对象数组的方式可以排序,排序语句:
    
    "sort": [
    {
    "category.category1Souce": "asc"
    }
    View Code

    七:嵌套聚合 

    • 查询嵌套文档中onlinecategory.category2Sysno为11的且先按照onlinecategory.category3Souce升序在按照price降序排列
    • 增加 nested_path 和 nested_filter 重复查询条件的原因是:排序发生在查询执行之后 查询条件限定了只查询category2Sysno为11的文档,如果排序子句中不加入此条件,排序就是基于所有文档的onlinecategory.category3Souce来排序的,而不仅仅是"onlinecategory.category2Sysno": 11的文档【但是此处是不需要加的因为加不加都是正确的,只做演示,基于范围的筛选加了才有意义】
    • 可以聚合嵌套的文档,同时聚合本身也可以嵌套很多层

    聚合结果排序(聚合后,按照每个桶的_count数量排序)

    {
      "query": {
        "nested": {
          "path": "onlinecategory",
          "query": {
            "term": {
              "onlinecategory.category2Sysno": "11"
            }
          }
        }
      },
      "sort": [
        {
          "onlinecategory.category3Souce": {
            "order": "desc",
            "mode": "max",
            "nested_path": "onlinecategory",
            "nested_filter": {
              "term": {
                "onlinecategory.category2Sysno": 11
              }
            }
          }
        },
        {
          "price": {
            "order": "asc"
          }
        }
      ],
      "aggs": {
        "size_onlinecategory": {
          "nested": {
            "path": "onlinecategory"
          },
          "aggs": {
            "size_category3Sysno": {
              "terms": {
                "field": "onlinecategory.category3Sysno",
                "order": {
                  "_count": "desc"
                }
              }
            },
            "size_category2Sysno": {
              "terms": {
                "field": "onlinecategory.category2Sysno"
              }
            }
          }
        }
      }
    }
    View Code

    嵌套索引创建: 定义mapping:

    [ElasticsearchType(Name = "product")]
        public class NestProduct
        {
            [String(Store = true, Index = FieldIndexOption.NotAnalyzed)]
            public string Id { get; set; }
            [String(Store = true, Index = FieldIndexOption.Analyzed)]
            public string Name { get; set; }
            [String(Store = true, Index = FieldIndexOption.NotAnalyzed)]
            public string Stock { get; set; }
            [String(Store = true, Index = FieldIndexOption.NotAnalyzed)]
            public string Price { get; set; }
            [Nested(Name ="onlinecategory")] //Path ="onlinecategory" 也可以
            public List<NestCategory> Categorys { get; set; }
    
        }
    
        [ElasticsearchType(Name = "category")]
        public class NestCategory
        {
            [String(Store = true, Index = FieldIndexOption.Analyzed)]
            public string Category1Name { get; set; }
    
            [String(Store = true, Index = FieldIndexOption.NotAnalyzed)]
            public string Category1Sysno { get; set; }
    
            [String(Store = true, Index = FieldIndexOption.Analyzed)]
            public string Category2Name { get; set; }
    
            [String(Store = true, Index = FieldIndexOption.NotAnalyzed)]
            public string Category2Sysno { get; set; }
    
            [String(Store = true, Index = FieldIndexOption.Analyzed)]
            public string Category3Name { get; set; }
    
            [String(Store = true, Index = FieldIndexOption.NotAnalyzed)]
            public string Category3Sysno { get; set; }
    
        }
    View Code

    创建索引:

    var decriptior = new CreateIndexDescriptor("nestproduct").Mappings(map => map.Map<NestProduct>(m => m.AutoMap()));
    var response = ElasticSearchCommon.GetInstance().GetElasticClient().CreateIndex(decriptior);

    嵌套的查询,排序和聚合:

    /// <summary>
            /// 嵌套查询
            /// </summary>
            /// <returns></returns>
            public List<NestProduct> NestedSearch()
            {
               //搜索包含车厘子的且中类为12 小类为121的商品
    
                //嵌套查询条件
                List<QueryContainer> qc = new List<QueryContainer>();            
                qc.Add(new TermQuery { Field = "onlinecategory.category2Sysno", Value = "11" });
                //qc.Add(new TermQuery { Field = "onlinecategory.category3Sysno", Value = "121" });
                NestedQuery nestq = new NestedQuery { Path= "onlinecategory", Query=new BoolQuery() { Must= qc} };
                //非嵌套查询条件
                MatchPhraseQuery matchPhraseQuery = new MatchPhraseQuery { Field = "name", Query = "车厘子" };
    
                //组合上面的查询条件
                List<QueryContainer> qcall = new List<QueryContainer>();
                qcall.Add(nestq);
                qcall.Add(matchPhraseQuery);
                BoolQuery bq = new BoolQuery() { Must = qcall };
    
                //使用嵌套字段排序 
    
                //1 默认情况下,根文档的分数是这些嵌套文档分数的平均值。可以通过设置 score_mode 参数来控制这个得分策略,
                //相关策略有 avg (平均值), max (最大值), sum (加和) 和 none (直接返回 1.0 常数值分数)。
                //2 考虑将查询条件作为 NestedFilter 子句  https://www.elastic.co/guide/cn/elasticsearch/guide/current/nested-sorting.html 
                List<ISort> sortlist = new List<ISort>() ;
                sortlist.Add(new SortField() { Field = "onlinecategory.category3Souce", NestedPath= "onlinecategory",Mode= SortMode.Min, NestedFilter= bq,  Order = SortOrder.Ascending });
                sortlist.Add(new SortField() { Field = "price", Order = SortOrder.Ascending });
    
                //聚合
                //Dictionary<string, AggregationContainer> container = new Dictionary<string, AggregationContainer>();
                //container.Add
                //聚合嵌套
                NestedAggregation nestedAgg = new NestedAggregation("agg_onlinecategory")
                {
                    Path = "onlinecategory",
                    Aggregations = new TermsAggregation("agg_oc3sysno")
                    {
                        Field = "onlinecategory.category3Sysno",
                        Order = new List<TermsOrder>() { new TermsOrder() { Key = "_count", Order = SortOrder.Descending } }
                    }
                };
                //执行搜索
                SearchRequest<NestProduct> searchRequest = new SearchRequest<NestProduct>("nestproduct", "product")
                {
                    From = 0,
                    Size = 100,
                    Query = bq,
                    //Sort= sortlist
                    Aggregations= nestedAgg
    
                }; 
                var client = ElasticSearchCommon.GetInstance().GetElasticClient();
                var response = client.Search<NestProduct>(searchRequest);
    
                //结果处理
                List<NestProduct> prolist = new List<NestProduct>();
                foreach (var i in response.Hits)
                {
                    prolist.Add(i.Source);
                }
    
                //获取聚合信息
                List<NestCategory> nestcat = new List<NestCategory>();
                //获取指定的桶对象
                var buck = response.Aggs.Aggregations["agg_onlinecategory"] as SingleBucketAggregate;
                var termbuck = buck.Aggregations["agg_oc3sysno"] as BucketAggregate;
                foreach (KeyedBucket b in termbuck.Items)
                {
                    nestcat.Add(new NestCategory() { Category3Sysno = b.Key });
                }           
    
                return prolist;
            }
    View Code

    八: mapping父子 

    //创建父子类型mapping,在子类型上指定父类型是谁
    http://192.168.60.61:29200/qtorder
    {
        "mappings": {
            "order": {
                "properties": {
                    "sysno": {
                        "type": "string",
                        "index": "not_analyzed"
                    },
                    "uid": {
                        "type": "string",
                        "index": "not_analyzed"
                    },
                    "createTime": {
                        "type": "date",
                        "index": "not_analyzed"
                    }
                }
            },
            "orderItem": {
                "_parent": { //此处只需要指定父类型是谁即可
                    "type": "order"
                },
                "properties": {
                    "productname": {
                        "type": "string",
                        "index": "analyzed"
                    },
                    "productid": {
                        "type": "string",
                        "index": "not_analyzed"
                    },
                    "ordersysno": {
                        "type": "string",
                        "index": "not_analyzed"
                    }
                }
            }
        }
    }
    View Code

    插入嵌套关系的数据,例如一个订单里面有3个商品,那么对象关系是一个订单对象里包含了一个商品列表对象,列表里有3个商品数据;而我们需要创建一个订单类型索引数据为父文档,三个产品类型索引数据为子文档

      public class objmanger
        {
           //sysno为订单号,指定默认id为订单号(唯一的)
            public static List<order> CreateOrder()
            {
                List<order> orders = new List<order>();
                orders.Add(new order { id="1001", createTime="2016-07-01", sysno="1001", uid="u1" });
                orders.Add(new order { id = "1002", createTime = "2016-07-02", sysno = "1002", uid = "u2" });
                return orders;
    
            }
         //ordersysno为订单号,对应order对象里的sysno和id
            public static List<orderItem> CreateOrderItem()
            {
                List<orderItem> items = new List<orderItem>();
                items.Add(new orderItem { ordersysno = "1001", productid = "p0011", productname = "产品11" });
                items.Add(new orderItem { ordersysno = "1001", productid = "p0012", productname = "产品12" });
                items.Add(new orderItem { ordersysno = "1001", productid = "p0013", productname = "产品13" });
                items.Add(new orderItem { ordersysno = "1002", productid = "p0014", productname = "产品14" });
                items.Add(new orderItem { ordersysno = "1002", productid = "p0015", productname = "产品15" });
                items.Add(new orderItem { ordersysno = "1002", productid = "p0016", productname = "产品16" });
                return items;
            
            }
        }
    View Code

    插入数据 

      public static void createparent()
            {
                var client = ElasticSearchCommon.GetInstance().GetElasticClient();
                var des = new BulkDescriptor().Index("qtorder");
                var orders = objmanger.CreateOrder();
                foreach (var i in orders)
                {
                    des.Index<order>(o => o.Document(i));
                }
                var response = client.Bulk(des);
            }
    
            public static void createchild()
            {
                var client = ElasticSearchCommon.GetInstance().GetElasticClient();
                var des = new BulkDescriptor().Index("qtorder");
                var items = objmanger.CreateOrderItem();
                foreach (var i in items)
                {
                    des.Type("orderItem").Index<orderItem>(o => o.Document(i).Parent(i.ordersysno));
                }
                var response2 = client.Bulk(des);
                 
                //foreach(var i in items)
                //{
                //    var request = new IndexRequest<orderItem>("qtorder", "orderItem", i.productid);
                //    request.Document = i;
                //    request.Parent=i.orderid;
                //    var respon= client.Index(request);
                //}
                    
            
            }
    View Code

    查询

    查询子文档商品名称包含 “产品” 的父文档订单信息(只返回父文档信息):
    post    http://192.168.60.61:29200/qtorder/order/_search
    
    {
     "query":{
    "has_child": {                
          "type": "orderItem",         
          "query": {               
            "match": {
              "productname": "产品"
            }
          }
        }     }                     
    }
    
    
    返回结果:
    {
      "took": 8,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 2,
        "max_score": 1,
        "hits": [
          {
            "_index": "qtorder",
            "_type": "order",
            "_id": "1001",
            "_score": 1,
            "_source": {
              "id": "1001",
              "ordersysno": "1001",
              "uid": "u1",
              "createTime": "2016-07-01"
            }
          },
          {
            "_index": "qtorder",
            "_type": "order",
            "_id": "1002",
            "_score": 1,
            "_source": {
              "id": "1002",
              "ordersysno": "1002",
              "uid": "u2",
              "createTime": "2016-07-02"
            }
          }
        ]
      }
    }
    View Code 

      查询用户u1买过的所有商品,(根据父文档条件查询子文档信息,只返回子文档信息),注意,下面orderid就是上面的ordersysno,忘改:

     nest代码

    /// <summary>
            /// 嵌套查询 
            /// 使用嵌套在一些情况下不用聚合就能得到结果
            /// </summary>
            public static void query()
            { 
                 var client = ElasticSearchCommon.GetInstance().GetElasticClient();
                 //TypeName [] ts = new TypeName[] { "order"};             
                 var result = client.Search<order>(s => s
                     .Index("qtorder")
                     .Type("order")
                     //.Query(q => q.Term("uid", "u1"))
                     //.Query(q => q.HasChild<orderItem>(c => c.Type("orderItem").Query(cq => cq.Term("productid", "p0011"))))//查询买过商品p0011的 订单
                     .Query(q => q.HasChild<orderItem>(c => c.Type("orderItem").Query(cq => cq.Match(o => o.Name("productname").Query("苹果")))))//查询子文档商品名称包含苹果的父文档信息
                     );
                 IEnumerable<order> ss = result.Documents;
            }
    View Code
    //多个文档类型查询 
    public static void query()
            { 
                 var client = ElasticSearchCommon.GetInstance().GetElasticClient();
                 TypeName[] ts = new TypeName[] { "order", "giftOrder" };             
                 var result = client.Search<order>(s => s
                     .Index("qtorder")
                     .Type(ts)
                     //.Query(q => q.HasChild<orderItem>(c => c.Type("orderItem").Query(cq => cq.Term("productid", "p0011"))))//查询买过商品p0011的 订单
                     .Query(q => q.HasChild<orderItem>(c => c
                         .Type("orderItem").Query(cq => cq.Match(o => o.Name("productname").Query("产品")))
                         .Type("giftOrderItem").Query(cq => cq.Match(o => o.Name("productname").Query("产品")))
                         ))//查询子文档商品名称包含苹果的父文档信息
                     );
                 IEnumerable<order> ss = result.Documents;
            }
    View Code

    es 支持文档嵌套和父子文档,文档嵌套式内容嵌套,一个大文档里面包含多个小文档;父子文档是指为两个独立的文档类型建立父子关联关系;

    父子文档查询时也支持多个类型查询 

    文档id:同一文档类型下,文档id不能重复,同一索引不同类型下的两个文档id可以是相同的

    //查询订单内容包含“礼金”,且用户是2340458的订单号,父子条件同时查询
    http://192.168.60.61:29200/order20160801/giftOrder/_search
    {
        "query": {
            "bool": {
                "must": [
                    {
                        "term": {
                            "uid": "2340458"
                        }
                    },
                    {
                        "has_child": {
                            "type": "giftOrderProduct",
                            "query": {
                                "term": {
                                    "productName": "礼金"
                                }
                            }
                        }
                    }
                ]
            }
        }
    }
    View Code
    //查询根据多个子类型信息,已经父类型信息,查询多个父类型。查询用户23130购买过包含“电子“的商品的订单(包含普通订单和礼品卡订单)
    http://192.168.60.61:29200/order20160801/giftOrder,order/_search
    {
        "from":0,
        "size":100,
        "query": {
            "bool":{"should":[
            {"bool":{"must":[{"term": {"uid": "23130"}}, { "has_child": {"type": "giftOrderProduct","query": {"term": {"productName": "电子"}}}}]}},
            {"bool":{"must":[{"term": {"uid": "23130"}}, { "has_child": {"type": "orderProduct","query": {"term": {"productName": "电子"}}}}]}}
            ]}
        }
    }
    View Code

     

     

  • 相关阅读:
    《实战Java高并发程序设计》读书笔记一
    《实战Java高并发程序设计》读书笔记二
    SprintBoot学习(三)
    SprintBoot学习(二)
    SprintBoot学习(一)
    jQuery学习(三)
    jQuery学习(二)
    jQuery学习(一)
    利用activeX控件在网页里自动登录WIN2003远程桌面并实时控制
    上传读取Excel文件数据
  • 原文地址:https://www.cnblogs.com/shaner/p/5661071.html
Copyright © 2020-2023  润新知