springAlibaba + ollama + es 完成RAG知识库功能

模块梳理

一、整体架构关系图

二、核心流程图

2. 问答检索流程

三、模块与依赖配置表

模块 主要配置类 核心依赖 端口
父工程 (demo) pom.xml Spring AI 1.1.2, Spring Boot 3.4.6 -
RAG子工程 application.yml spring-ai-pdf-document-reader, elasticsearch-java 8081
Ollama配置 OllamaConfig.java spring-ai-ollama 11434
向量存储配置 VectorStoreConfig.java spring-ai-elasticsearch-store 9200

核心要点

  1. 文档处理: MultipartFile → InputStreamResource → PagePdfDocumentReader → TokenTextSplitter
  1. 向量存储: Document → EmbeddingModel(bge-m3) → ElasticsearchVectorStore
  1. 问答流程: 用户问题 → 向量检索 → 上下文构建 → deepseek-r1:7b → 答案
  1. 配置管理:所有配置通过 @Configuration 和 @Value 从 application.yml 注入

1.创建项目,创建一个maven项目,父工程

主要用于管理springAi相关的版本,目录结构如下

主工程的pom文件如下 大家可查阅阿里巴巴ai的官网: https://java2ai.com/docs/overview

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.fl</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>demo</name>
    <description>demo</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <modules>
        <module>ailibaba</module>
        <module>RAG</module>
    </modules>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <spring-boot.version>3.4.6</spring-boot.version>
        <spring-ai.version>1.1.2</spring-ai.version>
        <spring-ailibaba.version>1.0.0.2</spring-ailibaba.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-ollama</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud.ai</groupId>
                <artifactId>spring-ai-alibaba-bom</artifactId>
                <version>${spring-ailibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 3. PGVector 向量数据库 -->
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <!-- 阿里云代码库 -->
        <repository>
            <id>maven-ali</id>
            <url>https://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>always</updatePolicy>
                <checksumPolicy>fail</checksumPolicy>
            </snapshots>
        </repository>
    </repositories>
</project>

HTML, XML

2.创建子工程RAG

子工程的目录结构如下,主要是pom依赖,导入需要springalibaba-ai-es和es-java,还有pdf处理相关的依赖

RAG子工程pom文件

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.fl</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>RAG</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- ChatClient 向量存储拦截器(RAG 必需) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-advisors-vector-store</artifactId>
        </dependency>
        <!-- Elasticsearch 向量存储 -->
        <dependency>
            <groupId>co.elastic.clients</groupId>
            <artifactId>elasticsearch-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-elasticsearch-store</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-vector-store-elasticsearch</artifactId>
        </dependency>
        <!-- PDF 解析 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-pdf-document-reader</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.20</version>
        </dependency>
    </dependencies>
</project>

3.开发步骤

开发前提:需要用ollama拉取对应的模型,我这里使用的是deepseek-r1:7b 与 嵌入式模型 bge-m3:latest, 大家可以根据自己的电脑配置自行升级,拉取es windows版。

1.创建yml文件

我的配置都是默认配置,es在本地配置文件中关闭了ssl与账号密码校验,有疑问的可以自行网上检索,相关处理方法很多

java 复制代码
server:
  port: 8081
  servlet:
    encoding:
      enabled: true
      charset: UTF-8
      force: true
spring:
  application:
    name: alibaba
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        options:
          model: deepseek-r1:7b
      embedding:
        options:
          enabled: true
          model: bge-m3:latest
    vectorstore:
      elasticsearch:
        initialize-schema: true
        dimensions: 1024

  elasticsearch:
    uris: http://localhost:9200
file:
  upload:
    max-size: 50MB
    temp-dir: D:/temp/upload
#          model: qwen3:0.6b
#    dashscope:
#      api-key:

2.创建config对应的类

主要是ollama会话模型,嵌入式模型,es搜索相关的初始化配置 ollama会话模型配置类

java 复制代码
package org.fl.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.api.OllamaApi;
import org.springframework.ai.ollama.api.OllamaChatOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;


/**
 * Ollama配置类,用于创建和配置Ollama聊天模型及相关组件
 */
@Configuration
public class OllamaConfig {
    @Value("${spring.ai.ollama.base-url}")
    private String baseUrl;
    @Value("${spring.ai.ollama.chat.options.model}")
    private String model;

    /**
     * 创建并配置Ollama聊天模型Bean
     *
     * @return 配置好的OllamaChatModel实例
     */
    @Bean("myOllamaChatModel")
    @Primary
    public OllamaChatModel ollamaChatModel() {
        // 构建Ollama API客户端,设置基础URL
        OllamaApi ollamaApi = OllamaApi.builder()
                .baseUrl(baseUrl)
                .build();
        // 配置聊天选项,设置使用的模型
        OllamaChatOptions options = new OllamaChatOptions();
        options.setModel(model);
        // 构建并返回Ollama聊天模型实例
        return OllamaChatModel.builder()
                .ollamaApi(ollamaApi)
                .defaultOptions(options)
                .build();
    }

    /**
     * 创建并配置聊天客户端Bean
     *
     * @param ollamaChatModel Ollama聊天模型实例
     * @return 配置好的ChatClient实例
     */
    @Bean
    public ChatClient chatClient(OllamaChatModel ollamaChatModel) {
        // 构建聊天客户端,添加日志记录器和消息内存管理器,并设置默认选项
        return ChatClient.builder(ollamaChatModel).defaultAdvisors(new SimpleLoggerAdvisor())
                .defaultAdvisors(MessageChatMemoryAdvisor
                        .builder(MessageWindowChatMemory.builder()
                                .maxMessages(20).build())
                        .build())
                .defaultOptions(OllamaChatOptions.builder().model("deepseek-r1:7b").build()).build();
    }
}

es与向量模型与数据库配置类

这些配置可以直接从yaml获取,我懒得改,大家根据需求自己更改代码即可

java 复制代码
package org.fl.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
import org.springframework.ai.ollama.OllamaEmbeddingModel;
import org.springframework.ai.ollama.api.OllamaApi;
import org.springframework.ai.ollama.api.OllamaEmbeddingOptions;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.vectorstore.elasticsearch.ElasticsearchVectorStore;
import org.springframework.ai.vectorstore.elasticsearch.ElasticsearchVectorStoreOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * 配置向量存储相关组件的配置类。
 * 包括Elasticsearch客户端、嵌入模型以及向量存储实例的创建与初始化。
 */
@Configuration
public class VectorStoreConfig {

    /**
     * 创建并返回一个用于连接Elasticsearch的RestClient实例。
     * 默认连接地址为 http://localhost:9200。
     *
     * @return 初始化后的RestClient对象
     */
    @Bean
    public RestClient restClient() {
        return RestClient.builder(new HttpHost("localhost", 9200, "http"))
                .build();
    }

    /**
     * 构建并返回一个Elasticsearch向量存储(VectorStore)实例。
     * 使用自定义索引名称和维度设置,并启用自动初始化schema功能。
     *
     * @param restClient     用于与Elasticsearch通信的客户端
     * @param embeddingModel 嵌入模型,用于将文本转换为向量表示
     * @return 配置完成的ElasticsearchVectorStore实例
     */
    @Bean("myVectorStore")
    @Primary
    public VectorStore vectorStore(RestClient restClient, EmbeddingModel embeddingModel) {
        // 设置Elasticsearch向量存储选项
        ElasticsearchVectorStoreOptions options = new ElasticsearchVectorStoreOptions();
        options.setIndexName("custom-index");    // 可选:指定索引名,默认为"spring-ai-document-index"
        options.setDimensions(1024);             // 可选:设定向量维度,默认使用模型维度或1536,我拉取的模型只支持1024维度

        return ElasticsearchVectorStore.builder(restClient, embeddingModel)
                .options(options)                     // 可选:应用自定义选项
                .initializeSchema(true)               // 可选:是否在启动时初始化索引结构,默认false
                .batchingStrategy(new TokenCountBatchingStrategy()) // 可选:批处理策略,默认TokenCountBatchingStrategy
                .build();
    }

    /**
     * 创建并返回一个基于Ollama服务的嵌入模型(EmbeddingModel)实例。
     * 模型默认使用 bge-m3:latest,并通过本地Ollama API提供服务。
     *
     * @return 配置好的OllamaEmbeddingModel实例
     */
    @Bean
    @Primary
    public EmbeddingModel embeddingModel() {
        return OllamaEmbeddingModel.builder()
                .ollamaApi(OllamaApi.builder().baseUrl("http://localhost:11434").build()) // Ollama API基础URL
                .defaultOptions(OllamaEmbeddingOptions.builder().model("bge-m3:latest").build()) // 默认使用的模型
                .build();
    }
}

3.文件上传切片处理服务

pdf文档处理类

该类主要是将pdf文件使用ai提供的pdf方法切片,然后返回,后续存储至es嵌入式数据库中

java 复制代码
package org.fl.service;

import org.springframework.ai.document.Document;
import org.springframework.ai.reader.TextReader;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.transformer.splitter.TextSplitter;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.nio.file.Files;
import java.util.List;

/**
 * 文档处理服务类,用于接收上传的文件并将其解析为结构化文档列表。
 * 支持 PDF 和文本文件格式,并对文档进行切分处理以适配后续 AI 模型使用。
 */
@Service
public class DocumentService {

    /**
     * 处理上传的文件,根据文件类型选择不同的读取方式,最终返回经过切分的文档列表。
     *
     * @param file 用户上传的多部分文件对象,支持 PDF 或纯文本文件
     * @return 经过解析与切分后的文档列表,适用于向量嵌入等下游任务
     * @throws Exception 当文件为空、无法读取、处理失败或临时文件操作出错时抛出异常
     */
    public List<Document> processFile(MultipartFile file) throws Exception {
        // 前置校验:文件为空直接抛异常
        if (file.isEmpty()) {
            throw new IllegalArgumentException("上传的文件不能为空");
        }
        List<Document> documents;

        if (file.getOriginalFilename() != null && file.getOriginalFilename().toLowerCase().endsWith(".pdf")) {
            File tempFile = null;
            try {
                // 1. 创建临时文件(指定临时目录,避免跨系统路径问题)
                tempFile = Files.createTempFile("upload-", ".pdf").toFile();
                // 2. 传输文件到临时文件(关键:校验传输是否成功)
                file.transferTo(tempFile);
                // 校验临时文件是否存在且可读
                if (!tempFile.exists() || !tempFile.canRead()) {
                    throw new Exception("临时文件生成失败或不可读:" + tempFile.getAbsolutePath());
                }

                // 3. 改用 FileSystemResource 加载文件系统中的文件(核心修复点)
                FileSystemResource resource = new FileSystemResource(tempFile);
                PagePdfDocumentReader pdfReader = new PagePdfDocumentReader(resource);
                documents = pdfReader.read();

            } catch (Exception e) {
                throw new Exception("处理PDF文件失败:" + e.getMessage(), e); // 保留异常栈,便于排查
            } finally {
                // 4. 安全删除临时文件(确保文件已处理完成)
                if (tempFile != null && tempFile.exists()) {
                    boolean deleted = tempFile.delete();
                    if (!deleted) {
                        tempFile.deleteOnExit();
                        // 可选:打印日志提醒
                        System.err.println("临时文件立即删除失败,将在JVM退出时删除:" + tempFile.getAbsolutePath());
                    }
                }
            }
        } else {
            // 处理文本文件:读取输入流为字符串
            String content = new String(file.getInputStream().readAllBytes());
            documents = new TextReader(content).read();
        }

        // 文本切分:将长文档分成小块 内置有参数,可自行调参
        TextSplitter textSplitter = new TokenTextSplitter();
        return textSplitter.apply(documents);
    }
}

文档向量处理类

java 复制代码
package org.fl.service;

import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 文档向量服务类
 * 提供文档向量存储和语义搜索功能
 */
@Service
public class DocumentVectorService {
    @Resource(name = "myVectorStore")
    private VectorStore vectorStore;

    /**
     * 将文档(或文本块)添加到向量数据库
     *
     * @param documents 要添加的文档列表
     */
    public void addDocuments(List<Document> documents) {
        vectorStore.add(documents);
    }

    /**
     * 进行语义搜索
     *
     * @param query 搜索查询字符串
     * @return 返回与查询最相似的文档列表
     */
    public List<Document> search(String query) {
        // 构建搜索请求,返回最相似的5条记录
        SearchRequest searchRequest = SearchRequest.builder().topK(5).query(query).build();
        return vectorStore.similaritySearch(searchRequest);
    }
}

向量检索与大模型会话类

java 复制代码
package org.fl.service;

import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 提供基于向量检索与大语言模型的回答服务。
 * <p>
 * 该服务首先通过用户问题在向量库中检索最相关的文档片段,
 * 然后将这些文档作为上下文构建系统提示词,
 * 最终调用大语言模型生成专业、准确的回答。
 */
@Service
public class RetrievalService {
    @Resource(name = "myVectorStore")
    private VectorStore vectorStore;
    @Resource(name = "myOllamaChatModel")
    private OllamaChatModel chatModel; // 自动配置为 deepseek-r1:1.5b
    @Resource
    private ChatClient chatClient;

    /**
     * 根据用户的提问,从向量存储中检索相关信息,并结合大模型生成回答。
     *
     * @param userQuestion 用户提出的问题文本
     * @return 大模型根据检索到的上下文所生成的回答内容
     */
    public String retrieveAndAnswer(String userQuestion) {
        // 1. 检索:从向量库查找相关文档块
        List<Document> similarDocuments = vectorStore.similaritySearch(
                SearchRequest.builder().topK(5).query(userQuestion).build()// 返回最相似的5条
        );

        // 2. 构建增强提示词 (Prompt)
        String context = similarDocuments.stream()
                .map(Document::getText)
                .collect(Collectors.joining("\n\n"));

        String systemPrompt = """
                你是一个专业的文档助手,请严格根据以下上下文信息回答问题。
                如果上下文没有提供答案,请直接说"根据现有资料无法回答"。
                
                上下文信息:
                {context}
                """;
        SystemPromptTemplate promptTemplate = new SystemPromptTemplate(systemPrompt);
        Message message = promptTemplate.createMessage(Map.of("context", context));

        // 3. 生成:调用大模型获取最终答案
        String content = chatClient.prompt()
                .system(message.getText())
                .user(userQuestion)
                .call().content();
        return content;
    }
}

4.控制层

主要是测试请求,与返回数据等

java 复制代码
package org.fl.controller;

import jakarta.annotation.Resource;
import org.fl.service.DocumentService;
import org.fl.service.DocumentVectorService;
import org.fl.service.RetrievalService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.document.Document;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.api.OllamaChatOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

/**
 * OllamaRagController 类提供基于 RAG(Retrieval-Augmented Generation)的文档上传与问答功能。
 * 支持通过 REST 接口上传文档并进行向量化存储,以及根据问题检索相关内容并生成回答。
 */
@RestController
@RequestMapping("/Rag")
public class OllamaRagController {
    private static final Logger log = LoggerFactory.getLogger(OllamaRagController.class);
    @Resource(name = "myOllamaChatModel")
    private OllamaChatModel ollamaChatModel;

    private final ChatClient ollamaiChatClient;
    @Autowired
    private DocumentService documentService;
    @Autowired
    private DocumentVectorService vectorStoreService;
    @Autowired
    private RetrievalService retrievalService;

    /**
     * 构造函数,用于创建 OllamaRagController 实例,并初始化聊天客户端配置。
     *
     * @param builder ChatClient.Builder 对象,用于构建聊天客户端
     */
    private OllamaRagController(ChatClient.Builder builder) {
        // 配置聊天客户端,设置内存聊天记录、日志记录和默认模型选项
        this.ollamaiChatClient = builder
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .defaultAdvisors(MessageChatMemoryAdvisor
                        .builder(MessageWindowChatMemory.builder()
                                .maxMessages(20).build())
                        .build())
                .defaultOptions(OllamaChatOptions.builder().model("deepseek-r1:7b").build()).build();
    }

    /**
     * 处理文件上传请求。将上传的文件进行处理、切分并转化为向量后存入向量数据库中。
     *
     * @param file 用户上传的多部分文件对象
     * @return 成功信息字符串,表示文档已成功上传并完成向量化存储
     * @throws Exception 文件处理或向量化过程中可能抛出异常
     */
    @PostMapping("/upload")
    public String uploadDocument(@RequestParam("file") MultipartFile file) throws Exception {
        List<Document> chunks = documentService.processFile(file);
        vectorStoreService.addDocuments(chunks);
        return "文档 '" + file.getOriginalFilename() + "' 上传、切分并向量化存储成功!";
    }

    /**
     * 根据用户提出的问题从已有文档中检索相关信息,并结合大模型生成答案。
     *
     * @param question 用户提出的查询问题
     * @return 返回由检索内容支持的大模型生成的回答文本
     */
    @GetMapping("/ask")
    public String askQuestion(@RequestParam String question) {
        return retrievalService.retrieveAndAnswer(question);
    }
}

测试效果如下

文件上传,随便找个http工具即可

知识库查询

也可以加入自己的部分条件,例如排序

相关推荐
老陈头聊SEO2 小时前
长尾关键词对SEO的重要性及其优化策略总结
其他·搜索引擎·seo优化
Cx330❀2 小时前
Git 分支管理完全指南:从基础到团队协作
大数据·git·搜索引擎·全文检索
库库茯苓2 小时前
Kibana报错:Unable to retrieve version information from Elasticsearch nodes (解决方法)Window11环境
elasticsearch·kibana
nhdh2 小时前
ELK(elasticsearch-7.6.2,kibana-7-6-2,Logstash-7.6.2)单节点部署
大数据·elk·elasticsearch
新元代码2 小时前
Git在Windows环境下的安装与使用教程
大数据·elasticsearch·搜索引擎
小园子的小菜2 小时前
深入理解Elasticsearch内部线程池:类型与核心作用解析
大数据·elasticsearch·搜索引擎
梦里不知身是客113 小时前
flume的数据模型介绍
大数据·flume
winfield8213 小时前
推荐/搜索系统的召回、精排、粗排、打散这四个环节都是做什么的?
大数据·人工智能
写代码的【黑咖啡】3 小时前
大数据中的数据同步预处理:保障数据质量的第一道防线
大数据