简体   繁体   English

弹性搜索索引

[英]ElasticSearch index

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

Liquibase only makes changes to your database. Liquibase 仅对您的数据库进行更改。 Unless you have some process which listens to the database changes and then updates Elasticsearch, you will not see the changes.除非您有一些进程可以监听数据库更改然后更新 Elasticsearch,否则您将看不到这些更改。

There might be multiple ways to get your database records into Elasticsearch:可能有多种方法可以将您的数据库记录放入 Elasticsearch:

  1. Your UI probably calls some back-end code to index a create or an update into Elasticsearch already您的 UI 可能会调用一些后端代码来将创建或更新索引到 Elasticsearch 中
  2. Have a batch process which knows which records are changed (eg use an updated flag column or a updated_timestamp column) and then index those into Elasticsearch.有一个批处理知道哪些记录被更改(例如使用更新的标志列或更新的时间戳列),然后将它们索引到 Elasticsearch 中。

The second option can either be done in code using a scripting or back-end scheduled job or you might be able to use Logstash with the jdbc-input plugin.第二个选项可以使用脚本或后端计划作业在代码中完成,或者您可以将 Logstash 与 jdbc-input 插件一起使用。

As Sarwar Bhuiyan and Mogsdad sad就像Sarwar BhuiyanMogsdad 一样悲伤

Unless you have some process which listens to the database changes and then updates Elasticsearch除非您有一些进程可以侦听数据库更改然后更新 Elasticsearch

You can use liquibase to populate elasticsearch(this task will be executed once, just like normal migration).您可以使用 liquibase 来填充 elasticsearch(此任务将执行一次,就像正常迁移一样)。 To do this you need to create a customChange :为此,您需要创建一个customChange

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

In that java based migration you can call the services you need.在基于 Java 的迁移中,您可以调用所需的服务。 Here is an example of what you can do ( please do not use code from this example in a production ).这是您可以做什么的示例(请不要在生产中使用此示例中的代码)。

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());
        }

    }

}

Because the beans have not yet been created, we will have to wait for them因为 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();

    }

}

An entity example:实体示例:

@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