This commit is contained in:
@@ -5,16 +5,13 @@ import fr.codeanddata.semrack.core.SemdocStorage;
|
|||||||
import fr.codeanddata.semrack.core.models.*;
|
import fr.codeanddata.semrack.core.models.*;
|
||||||
import fr.codeanddata.semrack.core.services.SemrackLookupService;
|
import fr.codeanddata.semrack.core.services.SemrackLookupService;
|
||||||
import fr.codeanddata.semrack.core.utils.Traverser;
|
import fr.codeanddata.semrack.core.utils.Traverser;
|
||||||
import fr.codeanddata.semrack.index.postgres.entities.IndexDocumentEntity;
|
import fr.codeanddata.semrack.index.postgres.dtos.IndexEntry;
|
||||||
import fr.codeanddata.semrack.index.postgres.entities.IndexKeyEntity;
|
import fr.codeanddata.semrack.index.postgres.entities.SemrackIndexEntity;
|
||||||
import fr.codeanddata.semrack.index.postgres.repositories.IndexDocumentRepository;
|
import fr.codeanddata.semrack.index.postgres.repositories.SemrackIndexRepository;
|
||||||
import fr.codeanddata.semrack.index.postgres.repositories.IndexKeyRepository;
|
|
||||||
import io.quarkus.hibernate.reactive.panache.PanacheRepository;
|
import io.quarkus.hibernate.reactive.panache.PanacheRepository;
|
||||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||||
import io.quarkus.hibernate.reactive.panache.common.WithTransaction;
|
import io.quarkus.hibernate.reactive.panache.common.WithTransaction;
|
||||||
import io.quarkus.vertx.ConsumeEvent;
|
|
||||||
import io.smallrye.mutiny.Uni;
|
import io.smallrye.mutiny.Uni;
|
||||||
import io.vertx.core.eventbus.EventBus;
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import org.hibernate.query.Page;
|
import org.hibernate.query.Page;
|
||||||
@@ -22,9 +19,7 @@ import org.hibernate.query.Page;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class SemdocJpaIndex implements SemdocIndex, PanacheRepository<IndexKeyEntity> {
|
public class SemdocJpaIndex implements SemdocIndex, PanacheRepository<SemrackIndexEntity> {
|
||||||
|
|
||||||
public static final String INDEX_CONSUMER = "semdoc-jpa-index";
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Traverser traverser;
|
Traverser traverser;
|
||||||
@@ -36,18 +31,12 @@ public class SemdocJpaIndex implements SemdocIndex, PanacheRepository<IndexKeyEn
|
|||||||
SemdocStorage storage;
|
SemdocStorage storage;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
IndexDocumentRepository indexDocumentRepository;
|
SemrackIndexRepository indexRepository;
|
||||||
|
|
||||||
@Inject
|
|
||||||
IndexKeyRepository indexKeyRepository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
EventBus bus;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@WithSession
|
@WithSession
|
||||||
public Uni<Long> count(SearchRequest request) {
|
public Uni<Long> count(SearchRequest request) {
|
||||||
final StringBuilder query = new StringBuilder("SELECT DISTINCT count(d.id) FROM index_document d JOIN index_key idx on d.id = idx.index_document_id");
|
final StringBuilder query = new StringBuilder("SELECT DISTINCT count(uid) FROM semrack_index");
|
||||||
|
|
||||||
final String lookup = lookupService.lookup(request.getFilter());
|
final String lookup = lookupService.lookup(request.getFilter());
|
||||||
final String whereClause = lookup.isEmpty() ? "" : " WHERE " + lookup;
|
final String whereClause = lookup.isEmpty() ? "" : " WHERE " + lookup;
|
||||||
@@ -67,29 +56,23 @@ public class SemdocJpaIndex implements SemdocIndex, PanacheRepository<IndexKeyEn
|
|||||||
public Uni<Void> index(String documentId) {
|
public Uni<Void> index(String documentId) {
|
||||||
return storage.get(documentId)
|
return storage.get(documentId)
|
||||||
.call(document -> clear(documentId))
|
.call(document -> clear(documentId))
|
||||||
.call(document -> indexDocumentRepository.persist(IndexDocumentEntity.builder()
|
.call(document -> {
|
||||||
.uid(documentId)
|
final Map<String, IndexEntry> indexes = new HashMap<>();
|
||||||
.build())
|
final List<TraverserPath> annotationPaths = traverser.apply(document.getAnnotations()).stream().peek(x -> x.setFullPath("annotations" + x.getFullPath())).toList();
|
||||||
.call(index -> {
|
final List<TraverserPath> metadataPaths = traverser.apply(document.getMetadata()).stream().peek(x -> x.setFullPath("metadata" + x.getFullPath())).toList();
|
||||||
final List<TraverserPath> annotationPaths = traverser.apply(document.getAnnotations()).stream().peek(x -> x.setFullPath("annotations" + x.getFullPath())).toList();
|
final List<TraverserPath> allPaths = new ArrayList<>();
|
||||||
final List<TraverserPath> metadataPaths = traverser.apply(document.getMetadata()).stream().peek(x -> x.setFullPath("metadata" + x.getFullPath())).toList();
|
allPaths.addAll(annotationPaths);
|
||||||
|
allPaths.addAll(metadataPaths);
|
||||||
|
allPaths.forEach(x -> indexes.put(x.getFullPath(), IndexEntry.builder()
|
||||||
|
.type(x.getType())
|
||||||
|
.value(x.getValue())
|
||||||
|
.build()));
|
||||||
|
|
||||||
final List<TraverserPath> allPaths = new ArrayList<>();
|
return indexRepository.persist(SemrackIndexEntity.builder()
|
||||||
allPaths.addAll(annotationPaths);
|
.uid(document.getUid())
|
||||||
allPaths.addAll(metadataPaths);
|
.indexes(indexes)
|
||||||
return indexKeyRepository.persist(allPaths
|
.build());
|
||||||
.stream()
|
})
|
||||||
.map(path -> {
|
|
||||||
final Map<String, Object> values = new HashMap<>();
|
|
||||||
values.put("v", path.getValue());
|
|
||||||
return IndexKeyEntity.builder()
|
|
||||||
.index(index)
|
|
||||||
.type(path.getType())
|
|
||||||
.fullPath(path.getFullPath())
|
|
||||||
.value(values)
|
|
||||||
.build();
|
|
||||||
}));
|
|
||||||
}))
|
|
||||||
.replaceWithVoid();
|
.replaceWithVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,12 +80,11 @@ public class SemdocJpaIndex implements SemdocIndex, PanacheRepository<IndexKeyEn
|
|||||||
@WithSession
|
@WithSession
|
||||||
public Uni<IndexSearchResult> search(SearchRequest request) {
|
public Uni<IndexSearchResult> search(SearchRequest request) {
|
||||||
final IndexSearchResult result = new IndexSearchResult();
|
final IndexSearchResult result = new IndexSearchResult();
|
||||||
final StringBuilder query = new StringBuilder("SELECT DISTINCT d.uid FROM index_document d JOIN index_key idx on d.id = idx.index_document_id");
|
final StringBuilder query = new StringBuilder("SELECT DISTINCT uid FROM semrack_index");
|
||||||
|
|
||||||
final String lookup = lookupService.lookup(request.getFilter());
|
final String lookup = lookupService.lookup(request.getFilter());
|
||||||
final String whereClause = lookup.isEmpty() ? "" : " WHERE " + lookup;
|
final String whereClause = lookup.isEmpty() ? "" : " WHERE " + lookup;
|
||||||
query.append(whereClause);
|
query.append(whereClause);
|
||||||
query.append(" GROUP BY d.uid");
|
|
||||||
|
|
||||||
return getSession()
|
return getSession()
|
||||||
.chain(s -> queryPaginationInfo(request)
|
.chain(s -> queryPaginationInfo(request)
|
||||||
@@ -119,8 +101,7 @@ public class SemdocJpaIndex implements SemdocIndex, PanacheRepository<IndexKeyEn
|
|||||||
@WithTransaction
|
@WithTransaction
|
||||||
public Uni<Void> clear(String documentId) {
|
public Uni<Void> clear(String documentId) {
|
||||||
return Uni.createFrom().nullItem()
|
return Uni.createFrom().nullItem()
|
||||||
.call(() -> IndexKeyEntity.delete("index.uid = ?1", documentId))
|
.call(() -> SemrackIndexEntity.delete("uid = ?1", documentId))
|
||||||
.call(() -> IndexDocumentEntity.delete("uid = ?1", documentId))
|
|
||||||
.replaceWithVoid();
|
.replaceWithVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package fr.codeanddata.semrack.index.postgres.dtos;
|
||||||
|
|
||||||
|
import fr.codeanddata.semrack.core.utils.Traverser;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class IndexEntry {
|
||||||
|
Traverser.PathTypes type;
|
||||||
|
Object value;
|
||||||
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package fr.codeanddata.semrack.index.postgres.entities;
|
|
||||||
|
|
||||||
import io.quarkus.hibernate.reactive.panache.PanacheEntity;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Entity(name = "IndexDocument")
|
|
||||||
@Table(name = "index_document")
|
|
||||||
public class IndexDocumentEntity extends PanacheEntity {
|
|
||||||
|
|
||||||
@Column(nullable = false, unique = true, columnDefinition = "varchar(256)")
|
|
||||||
String uid;
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package fr.codeanddata.semrack.index.postgres.entities;
|
|
||||||
|
|
||||||
import fr.codeanddata.semrack.core.utils.Traverser;
|
|
||||||
import io.quarkus.hibernate.reactive.panache.PanacheEntity;
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import lombok.*;
|
|
||||||
import org.hibernate.annotations.JdbcTypeCode;
|
|
||||||
import org.hibernate.type.SqlTypes;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Entity(name = "IndexAnnotation")
|
|
||||||
@Table(name = "index_key")
|
|
||||||
public class IndexKeyEntity extends PanacheEntity {
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "index_document_id", nullable = false)
|
|
||||||
IndexDocumentEntity index;
|
|
||||||
|
|
||||||
@Column(name = "fullpath")
|
|
||||||
String fullPath;
|
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
Traverser.PathTypes type;
|
|
||||||
|
|
||||||
@JdbcTypeCode(SqlTypes.JSON)
|
|
||||||
Map<String, Object> value;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package fr.codeanddata.semrack.index.postgres.entities;
|
||||||
|
|
||||||
|
import fr.codeanddata.semrack.index.postgres.dtos.IndexEntry;
|
||||||
|
import io.quarkus.hibernate.reactive.panache.PanacheEntity;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.*;
|
||||||
|
import org.hibernate.annotations.JdbcTypeCode;
|
||||||
|
import org.hibernate.type.SqlTypes;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Entity(name = "SemrackIndex")
|
||||||
|
@Table(name = "semrack_index")
|
||||||
|
public class SemrackIndexEntity extends PanacheEntity {
|
||||||
|
|
||||||
|
@Column(nullable = false, unique = true, columnDefinition = "varchar(256)")
|
||||||
|
String uid;
|
||||||
|
|
||||||
|
@JdbcTypeCode(SqlTypes.JSON)
|
||||||
|
Map<String, IndexEntry> indexes;
|
||||||
|
}
|
||||||
@@ -18,6 +18,6 @@ public class AndLookup implements SemrackJpaLookupExpression<List<Map<String, Ob
|
|||||||
@Override
|
@Override
|
||||||
public String apply(Object expressions) {
|
public String apply(Object expressions) {
|
||||||
final List<Map<String, Object>> typedExpressions = convert(expressions);
|
final List<Map<String, Object>> typedExpressions = convert(expressions);
|
||||||
return String.join(" AND ", typedExpressions.stream().map(lookupService::lookup).toList());
|
return "(" + String.join(" AND ", typedExpressions.stream().map(lookupService::lookup).toList()) + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class EqualLookup implements SemrackJpaLookupExpression<EqualLookupParams
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return "(idx.fullpath = '"+ equalLookupParams.getField() + "' AND idx.value->'v' = '"+ objectMapper.writeValueAsString(equalLookupParams.getValue())+"'::jsonb)";
|
return "(indexes->'"+ equalLookupParams.getField() + "'->'value' = '"+ objectMapper.writeValueAsString(equalLookupParams.getValue())+"'::jsonb)";
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class InLookup implements SemrackJpaLookupExpression<InLookupParams> {
|
|||||||
for (Object value : inLookupParams.getValues()) {
|
for (Object value : inLookupParams.getValues()) {
|
||||||
inValues.add("'" + objectMapper.writeValueAsString(value) + "'::jsonb");
|
inValues.add("'" + objectMapper.writeValueAsString(value) + "'::jsonb");
|
||||||
}
|
}
|
||||||
return "(idx.fullpath = '" + inLookupParams.getField() + "' AND idx.value->'v' in (" + String.join(",", inValues) + "))";
|
return "(indexes->'" + inLookupParams.getField() + "'->'value' in (" + String.join(",", inValues) + "))";
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ public class OrLookup implements SemrackJpaLookupExpression<List<Map<String, Obj
|
|||||||
@Override
|
@Override
|
||||||
public String apply(Object expressions) {
|
public String apply(Object expressions) {
|
||||||
final List<Map<String, Object>> typedExpressions = convert(expressions);
|
final List<Map<String, Object>> typedExpressions = convert(expressions);
|
||||||
return String.join(" OR ", typedExpressions.stream().map(lookupService::lookup).toList());
|
return "(" + String.join(" OR ", typedExpressions.stream().map(lookupService::lookup).toList()) + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package fr.codeanddata.semrack.index.postgres.repositories;
|
|
||||||
|
|
||||||
import fr.codeanddata.semrack.index.postgres.entities.IndexDocumentEntity;
|
|
||||||
import io.quarkus.hibernate.reactive.panache.PanacheRepository;
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
public class IndexDocumentRepository implements PanacheRepository<IndexDocumentEntity> {
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package fr.codeanddata.semrack.index.postgres.repositories;
|
package fr.codeanddata.semrack.index.postgres.repositories;
|
||||||
|
|
||||||
import fr.codeanddata.semrack.index.postgres.entities.IndexKeyEntity;
|
import fr.codeanddata.semrack.index.postgres.entities.SemrackIndexEntity;
|
||||||
import io.quarkus.hibernate.reactive.panache.PanacheRepository;
|
import io.quarkus.hibernate.reactive.panache.PanacheRepository;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class IndexKeyRepository implements PanacheRepository<IndexKeyEntity> {
|
public class SemrackIndexRepository implements PanacheRepository<SemrackIndexEntity> {
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
drop sequence if exists index_document_SEQ;
|
||||||
|
drop sequence if exists index_key_SEQ;
|
||||||
|
|
||||||
|
drop table if exists index_key;
|
||||||
|
drop table if exists index_document;
|
||||||
|
|
||||||
|
create table semrack_index
|
||||||
|
(
|
||||||
|
id bigint NOT NULL,
|
||||||
|
uid varchar(256) NOT NULL,
|
||||||
|
indexes jsonb,
|
||||||
|
constraint pk_semrack_index primary key (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
alter table semrack_index
|
||||||
|
add constraint uc_semrack_index_uid unique (uid);
|
||||||
|
|
||||||
|
create sequence semrack_index_SEQ start with 1 increment by 50;
|
||||||
2
pom.xml
2
pom.xml
@@ -32,7 +32,7 @@
|
|||||||
<lombok.version>1.18.38</lombok.version>
|
<lombok.version>1.18.38</lombok.version>
|
||||||
<org.mapstruct.version>1.6.3</org.mapstruct.version>
|
<org.mapstruct.version>1.6.3</org.mapstruct.version>
|
||||||
<semrack.version>1.0-SNAPSHOT</semrack.version>
|
<semrack.version>1.0-SNAPSHOT</semrack.version>
|
||||||
<quarkus.version>3.27.0</quarkus.version>
|
<quarkus.version>3.29.4</quarkus.version>
|
||||||
<jsonpath.version>2.9.0</jsonpath.version>
|
<jsonpath.version>2.9.0</jsonpath.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user