Soft delete articles

This commit is contained in:
Hongbo Wu 2022-07-29 15:53:13 +08:00
parent 07c6214e88
commit 83f988bb35
7 changed files with 67 additions and 48 deletions

View file

@ -18,7 +18,7 @@ export const addLabelInPage = async (
ctx._source.labels = [params.label];
ctx._source.updatedAt = params.updatedAt
} else if (!ctx._source.labels.any(label -> label.name == params.label.name)) {
ctx._source.labels.add(params.label) ;
ctx._source.labels.add(params.label);
ctx._source.updatedAt = params.updatedAt
} else { ctx.op = 'none' }`,
lang: 'painless',

View file

@ -2,6 +2,7 @@ import {
ArticleSavingRequestStatus,
Page,
PageContext,
PageSearchArgs,
PageType,
ParamSet,
SearchBody,
@ -17,7 +18,6 @@ import {
ReadFilter,
SortBy,
SortOrder,
SortParams,
} from '../utils/search'
import { client, INDEX_ALIAS } from './index'
import { EntityType } from '../datalayer/pubsub'
@ -337,21 +337,7 @@ export const getPageById = async (id: string): Promise<Page | undefined> => {
}
export const searchPages = async (
args: {
from?: number
size?: number
sort?: SortParams
query?: string
inFilter?: InFilter
readFilter?: ReadFilter
typeFilter?: PageType
labelFilters: LabelFilter[]
hasFilters: HasFilter[]
dateFilters: DateFilter[]
termFilters?: FieldFilter[]
matchFilters?: FieldFilter[]
includePending?: boolean | null
},
args: PageSearchArgs,
userId: string
): Promise<[Page[], number] | undefined> => {
try {
@ -448,6 +434,14 @@ export const searchPages = async (
})
}
if (!args.includeDeleted) {
body.query.bool.must_not.push({
term: {
state: ArticleSavingRequestStatus.Deleted,
},
})
}
console.log('searching pages in elastic', JSON.stringify(body))
const response = await client.search<SearchResponse<Page>, SearchBody>({
@ -533,6 +527,7 @@ export const deletePagesByParam = async <K extends keyof ParamSet>(
const { body } = await client.deleteByQuery({
index: INDEX_ALIAS,
body: params,
conflicts: 'proceed',
})
if (body.deleted > 0) {
@ -566,6 +561,11 @@ export const searchAsYouType = async (
userId,
},
},
{
term: {
state: ArticleSavingRequestStatus.Succeeded,
},
},
{
multi_match: {
query,

View file

@ -1,6 +1,15 @@
// Define the type of the body for the Search request
import { PickTuple } from '../util'
import { PubsubClient } from '../datalayer/pubsub'
import {
DateFilter,
FieldFilter,
HasFilter,
InFilter,
LabelFilter,
ReadFilter,
SortParams,
} from '../utils/search'
export interface SearchBody {
query: {
@ -246,3 +255,20 @@ export interface PageContext {
refresh?: boolean
uid: string
}
export interface PageSearchArgs {
from?: number
size?: number
sort?: SortParams
query?: string
inFilter?: InFilter
readFilter?: ReadFilter
typeFilter?: PageType
labelFilters: LabelFilter[]
hasFilters: HasFilter[]
dateFilters: DateFilter[]
termFilters?: FieldFilter[]
matchFilters?: FieldFilter[]
includePending?: boolean | null
includeDeleted?: boolean
}

View file

@ -82,7 +82,6 @@ import {
} from '../../elastic/types'
import {
createPage,
deletePage,
getPageById,
getPageByParam,
searchAsYouType,
@ -636,7 +635,12 @@ export const setBookmarkArticleResolver = authorized<
return { errorCodes: [SetBookmarkArticleErrorCode.NotFound] }
}
await deletePage(pageRemoved.id, { pubsub, uid })
// delete the page
await updatePage(
pageRemoved.id,
{ state: ArticleSavingRequestStatus.Deleted },
{ pubsub, uid }
)
const highlightsUnshared = await authTrx(async (tx) => {
return models.highlight.unshareAllHighlights(articleID, uid, tx)

View file

@ -70,11 +70,7 @@ describe('elastic api', () => {
],
state: ArticleSavingRequestStatus.Succeeded,
}
const pageId = await createPage(page, ctx)
if (!pageId) {
expect.fail('Failed to create page')
}
page.id = pageId
page.id = (await createPage(page, ctx))!
})
after(async () => {
@ -83,12 +79,10 @@ describe('elastic api', () => {
})
describe('createPage', () => {
let newPageId: string | undefined
let newPageId: string
after(async () => {
if (newPageId) {
await deletePage(newPageId, ctx)
}
await deletePage(newPageId, ctx)
})
it('creates a page', async () => {
@ -108,9 +102,7 @@ describe('elastic api', () => {
url: 'https://blog.omnivore.app/testUrl',
state: ArticleSavingRequestStatus.Succeeded,
}
newPageId = await createPage(newPageData, ctx)
newPageId = (await createPage(newPageData, ctx))!
expect(newPageId).to.be.a('string')
})
})
@ -344,9 +336,11 @@ describe('elastic api', () => {
})
describe('searchAsYouType', () => {
let pageId: string
before(async () => {
// create a testing page
await createPage(
pageId = (await createPage(
{
content: '',
createdAt: new Date(),
@ -363,12 +357,12 @@ describe('elastic api', () => {
userId,
},
ctx
)
))!
})
after(async () => {
// delete the testing page
await deletePagesByParam({ userId }, ctx)
await deletePage(pageId, ctx)
})
it('searches pages', async () => {

View file

@ -649,7 +649,7 @@ describe('Article API', () => {
let query = ''
let articleId = ''
let bookmark = true
let pageId = ''
let pageId: string
before(async () => {
const page: Page = {
@ -667,16 +667,11 @@ describe('Article API', () => {
readingProgressAnchorIndex: 0,
state: ArticleSavingRequestStatus.Succeeded,
}
const newPageId = await createPage(page, ctx)
if (newPageId) {
pageId = newPageId
}
pageId = (await createPage(page, ctx))!
})
after(async () => {
if (pageId) {
await deletePage(pageId, ctx)
}
await deletePage(pageId, ctx)
})
beforeEach(() => {
@ -684,7 +679,7 @@ describe('Article API', () => {
})
context('when we set a bookmark on an article', () => {
before(async () => {
before(() => {
articleId = pageId
bookmark = true
})
@ -698,15 +693,15 @@ describe('Article API', () => {
})
context('when we unset a bookmark on an article', () => {
before(async () => {
before(() => {
articleId = pageId
bookmark = false
})
it('should delete an article', async () => {
await graphqlRequest(query, authToken).expect(200)
const pageId = await getPageById(articleId)
expect(pageId).to.undefined
const page = await getPageById(articleId)
expect(page?.state).to.eql(ArticleSavingRequestStatus.Deleted)
})
})
})

View file

@ -11,7 +11,7 @@ import 'mocha'
import { User } from '../../src/entity/user'
import { Highlight, Page, PageContext } from '../../src/elastic/types'
import { getRepository } from '../../src/entity/utils'
import { deletePagesByParam, getPageById } from '../../src/elastic/pages'
import { deletePage, getPageById } from '../../src/elastic/pages'
import { addLabelInPage } from '../../src/elastic/labels'
import { createPubSubClient } from '../../src/datalayer/pubsub'
import {
@ -66,7 +66,7 @@ describe('Labels API', () => {
after(async () => {
// clean up
await deletePagesByParam({ userId: user.id }, ctx)
await deletePage(page.id, ctx)
await deleteTestUser(username)
})