Skip to content

Commit

Permalink
fix: find query mongodb properly with @DeleteDateColumn() (#9262)
Browse files Browse the repository at this point in the history
* fix: use existing query and filter deleted data

* test: add mongo-repository query test with DeleteDateColumn

* style: lint MongoEntityManager

* fix: not override $or with query.$or

* test: not override query.$or
  • Loading branch information
roseline124 committed Aug 24, 2022
1 parent 90ce285 commit e49d0c8
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 11 deletions.
26 changes: 17 additions & 9 deletions src/entity-manager/MongoEntityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ export class MongoEntityManager extends EntityManager {
),
)
if (deleteDateColumn && !optionsOrConditions.withDeleted) {
this.filterSoftDeleted(cursor, deleteDateColumn)
this.filterSoftDeleted(cursor, deleteDateColumn, query)
}
} else if (deleteDateColumn) {
this.filterSoftDeleted(cursor, deleteDateColumn)
this.filterSoftDeleted(cursor, deleteDateColumn, query)
}
return await cursor.toArray()
}
Expand Down Expand Up @@ -1168,8 +1168,16 @@ export class MongoEntityManager extends EntityManager {
protected filterSoftDeleted<Entity>(
cursor: Cursor<Entity>,
deleteDateColumn: ColumnMetadata,
query?: ObjectLiteral,
) {
cursor.filter({ $where: `this.${deleteDateColumn.propertyName}==null` })
const { $or, ...restQuery } = query ?? {}
cursor.filter({
$or: [
{ [deleteDateColumn.propertyName]: { $eq: null } },
...(Array.isArray($or) ? $or : []),
],
...restQuery,
})
}

/**
Expand Down Expand Up @@ -1214,10 +1222,10 @@ export class MongoEntityManager extends EntityManager {
),
)
if (deleteDateColumn && !findOneOptionsOrConditions.withDeleted) {
this.filterSoftDeleted(cursor, deleteDateColumn)
this.filterSoftDeleted(cursor, deleteDateColumn, query)
}
} else if (deleteDateColumn) {
this.filterSoftDeleted(cursor, deleteDateColumn)
this.filterSoftDeleted(cursor, deleteDateColumn, query)
}

// const result = await cursor.limit(1).next();
Expand Down Expand Up @@ -1256,10 +1264,10 @@ export class MongoEntityManager extends EntityManager {
),
)
if (deleteDateColumn && !optionsOrConditions.withDeleted) {
this.filterSoftDeleted(cursor, deleteDateColumn)
this.filterSoftDeleted(cursor, deleteDateColumn, query)
}
} else if (deleteDateColumn) {
this.filterSoftDeleted(cursor, deleteDateColumn)
this.filterSoftDeleted(cursor, deleteDateColumn, query)
}
return cursor.toArray()
}
Expand Down Expand Up @@ -1295,10 +1303,10 @@ export class MongoEntityManager extends EntityManager {
),
)
if (deleteDateColumn && !optionsOrConditions.withDeleted) {
this.filterSoftDeleted(cursor, deleteDateColumn)
this.filterSoftDeleted(cursor, deleteDateColumn, query)
}
} else if (deleteDateColumn) {
this.filterSoftDeleted(cursor, deleteDateColumn)
this.filterSoftDeleted(cursor, deleteDateColumn, query)
}
const [results, count] = await Promise.all<any>([
cursor.toArray(),
Expand Down
16 changes: 16 additions & 0 deletions test/functional/mongodb/basic/mongo-repository/entity/Post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Entity } from "../../../../../../src/decorator/entity/Entity"
import { Column } from "../../../../../../src/decorator/columns/Column"
import { ObjectIdColumn } from "../../../../../../src/decorator/columns/ObjectIdColumn"
import { ObjectID } from "../../../../../../src/driver/mongodb/typings"
import { DeleteDateColumn } from "../../../../../../src"

@Entity()
export class Post {
Expand All @@ -17,3 +18,18 @@ export class Post {
// @Column(() => Counters)
// counters: Counters;
}

@Entity()
export class PostWithDeleted {
@ObjectIdColumn()
id: ObjectID

@Column()
title: string

@Column()
text: string

@DeleteDateColumn()
deletedAt: Date | null
}
100 changes: 98 additions & 2 deletions test/functional/mongodb/basic/mongo-repository/mongo-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import {
createTestingConnections,
reloadTestingDatabases,
} from "../../../../utils/test-utils"
import { Post } from "./entity/Post"
import { Post, PostWithDeleted } from "./entity/Post"
import { MongoRepository } from "../../../../../src/repository/MongoRepository"

describe("mongodb > MongoRepository", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
entities: [Post],
entities: [Post, PostWithDeleted],
enabledDrivers: ["mongodb"],
})),
)
Expand Down Expand Up @@ -186,4 +186,100 @@ describe("mongodb > MongoRepository", () => {
expect(loadedPosts[0]).to.not.have.property("unreal")
}),
))

// Github issue #9250
describe("with DeletedDataColumn", () => {
it("with $or query", () =>
Promise.all(
connections.map(async (connection) => {
const postRepository =
connection.getMongoRepository(PostWithDeleted)
await seedPosts(postRepository)
const loadedPosts = await postRepository.find({
where: {
$or: [{ deletedAt: { $ne: null } }],
},
})
expect(loadedPosts).to.have.length(3)
}),
))

it("filter delete data", () =>
Promise.all(
connections.map(async (connection) => {
const postRepository =
connection.getMongoRepository(PostWithDeleted)
await seedPosts(postRepository)

const loadedPosts = await postRepository.find()
const filteredPost = loadedPosts.find(
(post) => post.title === "deleted",
)

expect(filteredPost).to.be.undefined
expect(loadedPosts).to.have.length(2)
}),
))

describe("findOne filtered data properly", () => {
it("findOne()", () =>
Promise.all(
connections.map(async (connection) => {
const postRepository =
connection.getMongoRepository(PostWithDeleted)
await seedPosts(postRepository)

const loadedPost = await postRepository.findOne({
where: { title: "notDeleted" },
})
const loadedPostWithDeleted =
await postRepository.findOne({
where: { title: "deleted" },
withDeleted: true,
})

expect(loadedPost?.title).to.eql("notDeleted")
expect(loadedPostWithDeleted?.title).to.eql("deleted")
}),
))

it("findOneBy()", () =>
Promise.all(
connections.map(async (connection) => {
const postRepository =
connection.getMongoRepository(PostWithDeleted)
await seedPosts(postRepository)

const loadedPost = await postRepository.findOneBy({
where: { title: "notDeleted" },
})
const loadedPostWithDeleted =
await postRepository.findOne({
where: { title: "deleted" },
withDeleted: true,
})

expect(loadedPost?.title).to.eql("notDeleted")
expect(loadedPostWithDeleted?.title).to.eql("deleted")
}),
))
})
})
})

async function seedPosts(postRepository: MongoRepository<PostWithDeleted>) {
await postRepository.save({
title: "withoutDeleted",
text: "withoutDeleted",
})
await postRepository.save({
title: "notDeleted",
text: "notDeleted",
deletedAt: null,
})
await postRepository.save({
title: "deleted",
text: "deleted",
deletedAt: new Date(),
})
}

0 comments on commit e49d0c8

Please sign in to comment.