# 拉取Elasticsearch官方Docker镜像
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.10.0
 
# 拉取Kibana官方Docker镜像
docker pull docker.elastic.co/kibana/kibana:7.10.0
 
# 运行Elasticsearch容器
docker run --name elasticsearch -d -p 9200:9200 -p 9300:9300 \
  -e "discovery.type=single-node" \
  docker.elastic.co/elasticsearch/elasticsearch:7.10.0
 
# 运行Kibana容器,并链接到Elasticsearch容器
docker run --name kibana -d -p 5601:5601 --link elasticsearch:elasticsearch \
  docker.elastic.co/kibana/kibana:7.10.0

这段代码首先从Elasticsearch和Kibana的官方Docker镜像库中拉取了所需的镜像,然后运行了Elasticsearch和Kibana的容器,并通过端口映射和链接选项配置了容器间的通信。这样,用户可以通过访问主机的9200和5601端口来使用Elasticsearch和Kibana服务。




import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.SearchHit;
 
public class ElasticSearchIntegration {
 
    public static void main(String[] args) throws IOException {
        // 初始化Elasticsearch客户端
        RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200, "http"));
        RestHighLevelClient client = new RestHighLevelClient(builder);
 
        // 创建一个搜索请求
        SearchRequest searchRequest = new SearchRequest("index_name"); // 替换为你的索引名
 
        // 设置搜索源
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("field_name", "value")); // 替换为你的字段名和值
        searchRequest.source(searchSourceBuilder);
 
        // 执行搜索
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
 
        // 处理搜索结果
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            System.out.println(hit.getSourceAsString());
        }
 
        // 关闭客户端
        client.close();
    }
}

这段代码展示了如何在Java中使用Elasticsearch的RestHighLevelClient进行基本的搜索操作。它创建了一个搜索请求,设置了搜索源,并执行了搜索。然后,它遍历并打印了搜索结果。最后,代码关闭了Elasticsearch客户端。这是一个简单的集成Elasticsearch的例子,但在实际应用中需要更多的错误处理和资源管理。

在Elasticsearch中,dense_vector 数据类型用于存储密集向量,这些向量可以用于相似度搜索。密集向量是一组数值,没有缺失数据。

以下是一个创建包含 dense_vector 类型字段的映射的示例:




PUT my_index
{
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "dense_vector",
        "dims": 3  // 指定向量的维度
      }
    }
  }
}

然后,您可以索引一个密集向量:




POST my_index/_doc/1
{
  "my_vector": [0.5, 10, 100.5]  // 向量的值
}

Elasticsearch 使用量化来优化向量的存储和搜索性能。量化是将向量中的每个数值除以一个量化范围(quantization\_gap),然后将结果舍入到最近的整数。这减少了需要存储的字节数,并允许更快的相似度搜索。

以下是一个量化向量搜索的示例:




POST my_index/_search
{
  "size": 10,
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "source": "cosineSimilarity(params.query_vector, 'my_vector') + 1.0",
        "params": {
          "query_vector": [0.7, 11, 101.5]  // 查询向量的值
        }
      }
    }
  }
}

在这个例子中,我们使用了一个脚本查询来计算查询向量和文档向量之间的余弦相似度,并将结果作为评分因子。这允许Elasticsearch执行基于向量相似度的查询。

CentOS 8 安装 Elasticsearch 的步骤如下:

  1. 导入Elasticsearch公钥:



sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
  1. 创建Elasticsearch的yum仓库文件:



echo "[elasticsearch-8.x]
name=Elasticsearch repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md" | sudo tee /etc/yum.repos.d/elasticsearch.repo
  1. 安装Elasticsearch:



sudo dnf install elasticsearch
  1. 启动并使Elasticsearch随系统启动:



sudo systemctl daemon-reload
sudo systemctl enable --now elasticsearch.service
  1. 检查Elasticsearch服务状态:



sudo systemctl status elasticsearch.service

以上步骤会安装Elasticsearch 8.x 版本。如果需要安装其他版本,请修改仓库文件中的版本号。安装完成后,您可以通过访问 http://<your-server-ip>:9200 来确认Elasticsearch是否正常运行。

在Elasticsearch中,分页查询是一个常见的操作。但是,分页查询有两个常见的问题,可能会导致数据不准确或性能问题。这里提供一个简单的避坑指南来解释和解决这些问题。

问题一:跳过的文档数太多

当你使用Elasticsearch进行分页查询时,你可能会使用fromsize参数来限定返回结果的范围。例如,如果你想跳过前10000个文档并获取之后的20个文档,你可能会这样做:




{
  "from": 10000,
  "size": 20
}

但是,随着from值的增加,Elasticsearch需要遍历的内部数据结构越多,这可能会导致查询性能下降。

解决方法:使用search after分页。

search after是一种更优的分页方法,它不需要跳过文档,而是记住上一次查询的最后一个文档的sort值,并且只需要获取这个sort值之后的文档。

问题二:深度分页的性能问题

随着分页的深入,获取结果所需的时间可能会显著增加,因为Elasticsearch需要访问大量的数据。

解决方法:使用索引差分查询或者时间范围查询。

如果你的查询是基于时间排序的,你可以只查询最近的一部分数据,并且只在必要时查看更早的数据。或者,你可以使用索引差分查询,只查询特定的索引或索引模式。

以上就是Elasticsearch分页查询的两个常见问题及其解决方法的简要说明。在实际应用中,你应该根据你的具体查询需求和数据量来选择最合适的分页策略。




import logging
 
# 创建Logger
logger = logging.getLogger('stressapptest')
logger.setLevel(logging.DEBUG)  # 设置日志级别为DEBUG
 
# 创建FileHandler,用于写入日志文件
log_file = 'stressapptest.log'
file_handler = logging.FileHandler(log_file)
file_handler.setLevel(logging.DEBUG)
 
# 创建StreamHandler,用于输出到控制台
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.ERROR)  # 仅输出ERROR及以上级别的日志
 
# 定义Handler的输出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
 
# 给Logger添加Handler
logger.addHandler(file_handler)
logger.addHandler(console_handler)
 
# 测试日志输出
logger.debug('这是一条debug级别的信息')
logger.info('这是一条info级别的信息')
logger.warning('这是一条warning级别的信息')
logger.error('这是一条error级别的信息')
logger.critical('这是一条critical级别的信息')
 
# 移除Handler,防止重复输出
logger.removeHandler(file_handler)
logger.removeHandler(console_handler)

这段代码首先创建了一个名为stressapptestLogger,并设置了日志级别为DEBUG。然后,它创建了一个FileHandler用于将日志写入文件,以及一个StreamHandler用于在控制台输出。定义了日志的格式并将其添加到Logger。最后,代码测试了不同级别的日志输出,并在完成后移除了Handler,以防止日志的重复输出。

要在Spring Boot中整合Elasticsearch 8.14.1,你需要做以下几步:

  1. 添加依赖到你的pom.xml文件中。
  2. 配置Elasticsearch客户端。
  3. 创建Repository接口。
  4. 使用Repository进行操作。

以下是一个简化的例子:

Step 1: 添加依赖




<dependencies>
    <!-- Spring Boot相关依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    <!-- Elasticsearch客户端 -->
    <dependency>
        <groupId>co.elastic.clients</groupId>
        <artifactId>elasticsearch-java</artifactId>
        <version>8.14.1</version>
    </dependency>
</dependencies>

Step 2: 配置Elasticsearch客户端




@Configuration
public class ElasticsearchConfig {
 
    @Value("${elasticsearch.host}")
    private String elasticsearchHost;
 
    @Value("${elasticsearch.port}")
    private int elasticsearchPort;
 
    @Bean
    public RestClient restClient() {
        return RestClient.builder(new HttpHost(elasticsearchHost, elasticsearchPort))
                .build();
    }
 
    @Bean
    public ElasticsearchTransport elasticsearchTransport(RestClient restClient) {
        return new RestClientTransport(restClient, new JacksonJsonSerializer());
    }
 
    @Bean
    public ElasticsearchClient elasticsearchClient(ElasticsearchTransport elasticsearchTransport) {
        return new ElasticsearchClient(elasticsearchTransport);
    }
}

Step 3: 创建Repository接口




public interface MyDocumentRepository {
    // 定义操作文档的方法
}

Step 4: 使用Repository




@Service
public class MyDocumentService {
 
    @Autowired
    private MyDocumentRepository myDocumentRepository;
 
    public void indexDocument(MyDocument document) {
        // 使用Repository索引文档
        myDocumentRepository.indexDocument(document);
    }
 
    public MyDocument getDocumentById(String id) {
        // 使用Repository通过ID获取文档
        return myDocumentRepository.getDocumentById(id);
    }
 
    // 其他操作...
}

注意:

  • 你需要定义MyDocument类,它应该与Elasticsearch中的文档映射。
  • 你需要实现MyDocumentRepository接口,这里没有给出具体实现,因为实现取决于你的Elasticsearch文档模型和所需的操作。
  • 配置中的elasticsearch.hostelasticsearch.port应该在你的application.propertiesapplication.yml文件中定义。
  • 这只是整合Elasticsearch的基本框架,具体的实现细节(例如文档的映射和数据模型)需要根据你的应用程序需求来定义。



import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
 
import java.io.IOException;
 
public class ElasticSearchQueryExample {
 
    public static void main(String[] args) throws IOException {
        // 初始化Elasticsearch客户端
        try (RestHighLevelClient client = new RestHighLevelClient(...)) {
            // 创建查询请求并设置索引
            SearchRequest searchRequest = new SearchRequest("index_name");
 
            // 构建查询条件
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(QueryBuilders.matchQuery("field_name", "value"));
 
            // 设置查询请求的源构建器
            searchRequest.source(searchSourceBuilder);
 
            // 执行查询
            SearchResponse searchResponse = client.search(searchRequest);
 
            // 处理查询结果
            SearchHits searchHits = searchResponse.getHits();
            for (SearchHit hit : searchHits) {
                System.out.println(hit.getSourceAsString());
            }
        }
    }
}

这段代码展示了如何使用Elasticsearch Java API Client进行基本的查询操作。它创建了一个匹配查询,查询字段field\_name的值为"value"的文档,并打印出返回结果的文档源数据。这是Elasticsearch搜索操作的基本示例,适用于入门级的Elasticsearch使用者。




import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
 
public class ElasticSearchDocumentExample {
    public static void main(String[] args) throws IOException {
        // 初始化RestHighLevelClient
        try (RestHighLevelClient client = new RestHighLevelClient(...)) {
            // 创建索引请求
            IndexRequest request = new IndexRequest("posts");
            
            // 设置索引文档的ID
            String jsonString = "{" +
                    "\"user\":\"kimchy\"," +
                    "\"postDate\":\"2023-04-07\"," +
                    "\"message\":\"trying out Elasticsearch\"" +
                    "}";
            request.source(jsonString, XContentType.JSON);
            
            // 执行请求,并获取响应
            IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
            
            // 打印索引操作的结果
            System.out.println("索引文档成功: " + indexResponse.getResult());
        }
    }
}

这段代码演示了如何使用RestHighLevelClient在Elasticsearch中创建和索引一个JSON文档。首先,创建了一个IndexRequest对象,并指定了要索引的文档和索引名称。然后,设置了文档的ID和要索引的JSON字符串内容。最后,使用RestHighLevelClientindex方法执行索引操作,并打印出操作结果。




PUT /_template/my_template
{
  "index_patterns": ["my_logs-*", "my_metrics-*"],
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1
  },
  "mappings": {
    "dynamic_templates": [
      {
        "message_field": {
          "path_match": "message",
          "match_mapping_type": "string",
          "mapping": {
            "type": "text"
          }
        }
      },
      {
        "long_strings": {
          "match_mapping_type": "string",
          "path_match": "*.description",
          "mapping": {
            "norms": false,
            "type": "keyword"
          }
        }
      }
    ],
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "geoip": {
        "dynamic": true,
        "properties": {
          "location": {
            "type": "geo_point"
          }
        }
      }
    }
  },
  "aliases": {
    "logs_write": {},
    "metrics_search": {
      "filter": {
        "term": {
          "type": "metric"
        }
      }
    }
  }
}

这个JSON例子展示了如何创建一个名为my_template的索引模板,它适用于所有匹配my_logs-*my_metrics-*模式的索引。它设置了索引的分片和副本数量,并定义了动态模板,用于处理字段类型的映射和别名,这些别名可以在写入数据时使用,并且在搜索指标类型数据时可以指定一个过滤器。