繁体   English   中英

弹性搜索索引

[英]ElasticSearch index

ElasticSearch 为 UI 创建的新记录做索引,但是 liquibase 文件创建的记录没有索引所以不会出现在搜索结果中,ElasticSearch 应该索引 UI 和 liquibase 文件创建的所有记录,是否有索引记录的过程liquibase 文件。

Liquibase 仅对您的数据库进行更改。 除非您有一些进程可以监听数据库更改然后更新 Elasticsearch,否则您将看不到这些更改。

可能有多种方法可以将您的数据库记录放入 Elasticsearch:

  1. 您的 UI 可能会调用一些后端代码来将创建或更新索引到 Elasticsearch 中
  2. 有一个批处理知道哪些记录被更改(例如使用更新的标志列或更新的时间戳列),然后将它们索引到 Elasticsearch 中。

第二个选项可以使用脚本或后端计划作业在代码中完成,或者您可以将 Logstash 与 jdbc-input 插件一起使用。

就像Sarwar BhuiyanMogsdad 一样悲伤

除非您有一些进程可以侦听数据库更改然后更新 Elasticsearch

您可以使用 liquibase 来填充 elasticsearch(此任务将执行一次,就像正常迁移一样)。 为此,您需要创建一个customChange

<customChange class="org.test.ElasticMigrationByEntityName">
    <param name="entityName" value="org.test.TestEntity" />
</customChange>

在基于 Java 的迁移中,您可以调用所需的服务。 这是您可以做什么的示例(请不要在生产中使用此示例中的代码)。

public class ElasticMigrationByEntityName implements CustomTaskChange {

    private String entityName;

    public String getEntityName() {
        return entityName;
    }

    public void setEntityName(String entityName) {
        this.entityName = entityName;
    }

    @Override
    public void execute(Database database) {
        //We schedule the task for the next execution. We are waiting for the context to start and we get access to the beans
        DelayedTaskExecutor.add(new DelayedTask(entityName));
    }

    @Override
    public String getConfirmationMessage() {
        return "OK";
    }

    @Override
    public void setUp() throws SetupException {

    }

    @Override
    public void setFileOpener(ResourceAccessor resourceAccessor) {

    }

    @Override
    public ValidationErrors validate(Database database) {
        return new ValidationErrors();
    }

    /* ===================== */

    public static class DelayedTask implements Consumer<ApplicationContext> {

        private final String entityName;

        public DelayedTask(String entityName) {
            this.entityName = entityName;
        }

        @Override
        public void accept(ApplicationContext applicationContext) {
            try {
                checkedAccept(applicationContext);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        //We're going to find beans by name (the most controversial point)
        private void checkedAccept(ApplicationContext context) throws ClassNotFoundException {
            Class entityClass = Class.forName(entityName);
            String name = entityClass.getSimpleName();

            //Please do not use this code in production
            String repositoryName = org.apache.commons.lang3.StringUtils.uncapitalize(name + "Repository");
            String repositorySearchName = org.apache.commons.lang3.StringUtils.uncapitalize(name + "SearchRepository");

            JpaRepository repository = (JpaRepository) context.getBean(repositoryName);
            ElasticsearchRepository searchRepository = (ElasticsearchRepository) context.getBean(repositorySearchName);

            //Doing our work
            updateData(repository, searchRepository);
        }

        //Write your logic here
        private void updateData(JpaRepository repository, ElasticsearchRepository searchRepository) {
            searchRepository.saveAll(repository.findAll());
        }

    }

}

因为 bean 尚未创建,我们将不得不等待它们

@Component
public class DelayedTaskExecutor {

    @Autowired
    private ApplicationContext context;

    @EventListener
    //We are waiting for the app to launch
    public void onAppReady(ApplicationReadyEvent event) {
        Queue<Consumer<ApplicationContext>> localQueue = getQueue();
        if(localQueue.size() > 0) {
            for (Consumer<ApplicationContext> consumer = localQueue.poll(); consumer != null; consumer = localQueue.poll()) {
                consumer.accept(context);
            }
        }
    }

    public static void add(Consumer<ApplicationContext> consumer) {
        getQueue().add(consumer);
    }

    public static Queue<Consumer<ApplicationContext>> getQueue() {
        return Holder.QUEUE;
    }

    private static class Holder {

        private static final Queue<Consumer<ApplicationContext>> QUEUE = new ConcurrentLinkedQueue();

    }

}

实体示例:

@Entity
@Table(name = "test_entity")
@Document(indexName = "testentity")
public class TestEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Field(type = FieldType.Keyword)
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String id;

    @NotNull
    @Column(name = "code", nullable = false, unique = true)
    private String code;

    ...

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM