Fix the problem of not being able to rebuild search index (#6323)

#### What type of PR is this?

/kind bug
/area core
/milestone 2.18.x

#### What this PR does / why we need it:

This PR fixes the problem of not being able to rebuild search index due to null description and updateTimestamp.

#### Which issue(s) this PR fixes:

Fixes #6317 

#### Does this PR introduce a user-facing change?

```release-note
修复无法正常刷新搜索引擎的问题
```
pull/6329/head
John Niang 2024-07-15 11:39:26 +08:00 committed by GitHub
parent 1089061265
commit 6bc13552ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 42 additions and 9 deletions

View File

@ -194,8 +194,11 @@ public class LuceneSearchEngine implements SearchEngine, InitializingBean, Dispo
}
var description = doc.get("description");
var hlDescription =
highlighter.getBestFragment(this.analyzer, "description", description);
String hlDescription = null;
if (description != null) {
hlDescription =
highlighter.getBestFragment(this.analyzer, "description", description);
}
var content = doc.get("content");
var hlContent = highlighter.getBestFragment(this.analyzer, "content", content);
@ -310,7 +313,9 @@ public class LuceneSearchEngine implements SearchEngine, InitializingBean, Dispo
}
doc.add(new TextField("title", haloDoc.getTitle(), YES));
doc.add(new TextField("description", haloDoc.getDescription(), YES));
if (haloDoc.getDescription() != null) {
doc.add(new TextField("description", haloDoc.getDescription(), YES));
}
doc.add(new TextField("content", haloDoc.getContent(), YES));
doc.add(new StringField("recycled", Boolean.toString(haloDoc.isRecycled()), YES));
doc.add(new StringField("exposed", Boolean.toString(haloDoc.isExposed()), YES));
@ -335,7 +340,9 @@ public class LuceneSearchEngine implements SearchEngine, InitializingBean, Dispo
var creationTimestamp = haloDoc.getCreationTimestamp();
doc.add(new LongField("creationTimestamp", creationTimestamp.toEpochMilli(), YES));
var updateTimestamp = haloDoc.getUpdateTimestamp();
doc.add(new LongField("updateTimestamp", updateTimestamp.toEpochMilli(), YES));
if (updateTimestamp != null) {
doc.add(new LongField("updateTimestamp", updateTimestamp.toEpochMilli(), YES));
}
doc.add(new StringField("permalink", haloDoc.getPermalink(), YES));
return doc;
}
@ -375,8 +382,11 @@ public class LuceneSearchEngine implements SearchEngine, InitializingBean, Dispo
var creationTimestamp = doc.getField("creationTimestamp").numericValue().longValue();
haloDoc.setCreationTimestamp(Instant.ofEpochMilli(creationTimestamp));
var updateTimestamp = doc.getField("updateTimestamp").numericValue().longValue();
haloDoc.setUpdateTimestamp(Instant.ofEpochMilli(updateTimestamp));
var updateTimestampField = doc.getField("updateTimestamp");
if (updateTimestampField != null) {
var updateTimestamp = updateTimestampField.numericValue().longValue();
haloDoc.setUpdateTimestamp(Instant.ofEpochMilli(updateTimestamp));
}
// handle content later
return haloDoc;
}

View File

@ -2,6 +2,7 @@ package run.halo.app.search.post;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.halo.app.content.ContentWrapper;
import run.halo.app.content.PostService;
import run.halo.app.core.extension.content.Post;
@ -36,6 +37,11 @@ public class PostHaloDocumentsProvider implements HaloDocumentsProvider {
// get content
return paginatedOperator.list(Post.class, options)
.flatMap(post -> postService.getReleaseContent(post)
.switchIfEmpty(Mono.fromSupplier(() -> ContentWrapper.builder()
.content("")
.raw("")
.rawType("")
.build()))
.map(contentWrapper -> convert(post, contentWrapper))
);
}

View File

@ -2,6 +2,7 @@ package run.halo.app.search.lucene;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.assertArg;
@ -160,7 +161,7 @@ class LuceneSearchEngineTest {
var gotHaloDoc = result.getHits().get(0);
assertEquals("fake-id", gotHaloDoc.getId());
assertEquals("<fake-tag>fake</fake-tag>-title", gotHaloDoc.getTitle());
assertEquals("<fake-tag>fake</fake-tag>-desc", gotHaloDoc.getDescription());
assertNull(gotHaloDoc.getDescription());
assertEquals("<fake-tag>fake</fake-tag>-content", gotHaloDoc.getContent());
}
@ -169,13 +170,13 @@ class LuceneSearchEngineTest {
haloDoc.setId("fake-id");
haloDoc.setMetadataName("fake-name");
haloDoc.setTitle("fake-title");
haloDoc.setDescription("fake-desc");
haloDoc.setDescription(null);
haloDoc.setContent("fake-content");
haloDoc.setType("fake-type");
haloDoc.setOwnerName("fake-owner");
var now = Instant.now();
haloDoc.setCreationTimestamp(now);
haloDoc.setUpdateTimestamp(now);
haloDoc.setUpdateTimestamp(null);
haloDoc.setPermalink("/fake-permalink");
haloDoc.setAnnotations(Map.of("fake-anno-key", "fake-anno-value"));
return haloDoc;

View File

@ -56,7 +56,23 @@ class PostHaloDocumentsProviderTest {
assertEquals("fake-content", doc.getContent());
})
.verifyComplete();
}
@Test
void shouldFetchAllIfNoContent() {
var post = createFakePost();
when(paginatedOperator.list(same(Post.class), any(ListOptions.class)))
.thenReturn(Flux.just(post));
when(postService.getReleaseContent(post)).thenReturn(Mono.empty());
provider.fetchAll()
.as(StepVerifier::create)
.assertNext(doc -> {
assertEquals("post.content.halo.run", doc.getType());
assertEquals("fake-post", doc.getMetadataName());
assertEquals("post.content.halo.run-fake-post", doc.getId());
assertEquals("", doc.getContent());
})
.verifyComplete();
}
Post createFakePost() {