search n count, offset
This commit is contained in:
@@ -1 +1,7 @@
|
|||||||
export class CreatePostDto {}
|
import {IsNotEmpty, IsString} from "class-validator";
|
||||||
|
|
||||||
|
export class CreatePostDto {
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsNotEmpty()
|
||||||
|
paragraphs: string[];
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ class Post {
|
|||||||
@Column()
|
@Column()
|
||||||
public content: string;
|
public content: string;
|
||||||
|
|
||||||
|
@Column('text', { array: true })
|
||||||
|
public paragraphs: string[];
|
||||||
|
|
||||||
@Column({nullable: true})
|
@Column({nullable: true})
|
||||||
public category?: string;
|
public category?: string;
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {CreatePostDto} from './dto/create-post.dto';
|
|||||||
import {UpdatePostDto} from './dto/update-post.dto';
|
import {UpdatePostDto} from './dto/update-post.dto';
|
||||||
import JwtAuthenticationGuard from "../authentication/jwt-authentication.guard";
|
import JwtAuthenticationGuard from "../authentication/jwt-authentication.guard";
|
||||||
import RequestWithUser from "../authentication/requestWithUser.interface";
|
import RequestWithUser from "../authentication/requestWithUser.interface";
|
||||||
|
import {PaginationParams} from "../utils/types/paginationParams";
|
||||||
|
|
||||||
@Controller('posts')
|
@Controller('posts')
|
||||||
@UseInterceptors(ClassSerializerInterceptor)
|
@UseInterceptors(ClassSerializerInterceptor)
|
||||||
@@ -31,11 +32,14 @@ export class PostsController {
|
|||||||
|
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async getPosts(@Query('search') search: string) {
|
async getPosts(
|
||||||
|
@Query('search') search: string,
|
||||||
|
@Query() { offset, limit }: PaginationParams
|
||||||
|
) {
|
||||||
if (search) {
|
if (search) {
|
||||||
return this.postsService.searchForPosts(search);
|
return this.postsService.searchForPosts(search, offset, limit);
|
||||||
}
|
}
|
||||||
return this.postsService.getAllPosts();
|
return this.postsService.getAllPosts(offset, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {CreatePostDto} from './dto/create-post.dto';
|
|||||||
import {UpdatePostDto} from './dto/update-post.dto';
|
import {UpdatePostDto} from './dto/update-post.dto';
|
||||||
import User from "../users/entities/user.entity";
|
import User from "../users/entities/user.entity";
|
||||||
import {InjectRepository} from "@nestjs/typeorm";
|
import {InjectRepository} from "@nestjs/typeorm";
|
||||||
import {Repository} from "typeorm";
|
import {FindManyOptions, MoreThan, Repository} from "typeorm";
|
||||||
import Post from './entities/post.entity';
|
import Post from './entities/post.entity';
|
||||||
import {PostNotFoundException} from "./exception/postNotFound.exception";
|
import {PostNotFoundException} from "./exception/postNotFound.exception";
|
||||||
import PostsSearchService from "./postsSearch.service";
|
import PostsSearchService from "./postsSearch.service";
|
||||||
@@ -27,7 +27,7 @@ export class PostsService {
|
|||||||
return newPost;
|
return newPost;
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchForPosts(text: string) {
|
async searchForPosts(text: string, offset?: number, limit?: number) {
|
||||||
const results = await this.postsSearchService.search(text);
|
const results = await this.postsSearchService.search(text);
|
||||||
const ids = results.flatMap(result => result.hits.hits.map(hit => hit._source.id));
|
const ids = results.flatMap(result => result.hits.hits.map(hit => hit._source.id));
|
||||||
if (!ids.length) {
|
if (!ids.length) {
|
||||||
@@ -39,10 +39,34 @@ export class PostsService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async getAllPosts(offset?: number, limit?: number, startId = 0) {
|
||||||
|
|
||||||
|
const where: FindManyOptions<Post>['where'] = {};
|
||||||
|
let separateCount = 0;
|
||||||
|
if (startId) {
|
||||||
|
where.id = MoreThan(startId);
|
||||||
|
separateCount = await this.repo.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
getAllPosts() {
|
const [items, count] = await this.repo.findAndCount({
|
||||||
return this.repo.find({relations: ['author']});
|
where,
|
||||||
|
relations: {
|
||||||
|
author: true
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
id: 'ASC'
|
||||||
|
},
|
||||||
|
skip: offset,
|
||||||
|
take: limit
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
count: startId ? separateCount : count
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPostById(id: number) {
|
async getPostById(id: number) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {ElasticsearchService} from '@nestjs/elasticsearch';
|
|||||||
import Post from "./entities/post.entity";
|
import Post from "./entities/post.entity";
|
||||||
import {PostSearchResult} from "./types/postSearchResult.interface";
|
import {PostSearchResult} from "./types/postSearchResult.interface";
|
||||||
import {PostSearchBody} from "./types/postSearchBody.interface";
|
import {PostSearchBody} from "./types/postSearchBody.interface";
|
||||||
|
import PostCountResult from "./types/postCountBody.interface";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export default class PostsSearchService {
|
export default class PostsSearchService {
|
||||||
@@ -25,6 +26,22 @@ export default class PostsSearchService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async count(query: string, fields: string[]) {
|
||||||
|
const result = await this.elasticsearchService.count({
|
||||||
|
index: this.index,
|
||||||
|
query: {
|
||||||
|
multi_match: {
|
||||||
|
query,
|
||||||
|
fields,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async search(text: string) {
|
async search(text: string) {
|
||||||
const result = await this.elasticsearchService.search<PostSearchResult>({
|
const result = await this.elasticsearchService.search<PostSearchResult>({
|
||||||
index: this.index,
|
index: this.index,
|
||||||
|
|||||||
5
src/posts/types/postCountBody.interface.ts
Normal file
5
src/posts/types/postCountBody.interface.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
interface PostCountResult {
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PostCountResult;
|
||||||
23
src/utils/types/paginationParams.ts
Normal file
23
src/utils/types/paginationParams.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { IsNumber, Min, IsOptional } from 'class-validator';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
|
||||||
|
export class PaginationParams {
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1)
|
||||||
|
startId?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
offset?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1)
|
||||||
|
limit?: number;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user