Skip to content

Commit

Permalink
Fixed updates
Browse files Browse the repository at this point in the history
It appeared that I made a shameless error with test assertions and
didn't catch the basic scenario.

This commit fixes it, enhances also other operators and adds additional
test coverage.

Fixes #21
  • Loading branch information
oskardudycz committed Jul 9, 2024
1 parent d87fbcd commit 5c80a7f
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 35 deletions.
6 changes: 3 additions & 3 deletions src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@event-driven-io/pongo-core",
"version": "0.2.3",
"version": "0.2.4",
"description": "Pongo - Mongo with strong consistency on top of Postgres",
"type": "module",
"engines": {
Expand Down
2 changes: 1 addition & 1 deletion src/packages/pongo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@event-driven-io/pongo",
"version": "0.2.3",
"version": "0.2.4",
"description": "Pongo - Mongo with strong consistency on top of Postgres",
"type": "module",
"scripts": {
Expand Down
123 changes: 103 additions & 20 deletions src/packages/pongo/src/e2e/compatibilityTest.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ void describe('MongoDB Compatibility Tests', () => {
},
);
});

void it('should insert many documents into both PostgreSQL and MongoDB', async () => {
const pongoCollection = pongoDb.collection<User>('insertMany');
const mongoCollection = mongoDb.collection<User>('insertMany');
Expand Down Expand Up @@ -162,14 +163,57 @@ void describe('MongoDB Compatibility Tests', () => {
_id: mongoInsertResult.insertedId,
});

assert.equal(mongoDoc?.age, 31);
assert.deepStrictEqual(
{
name: pongoDoc!.name,
age: 31,
age: pongoDoc!.age,
},
{
name: mongoDoc!.name,
age: 31,
age: mongoDoc!.age,
},
);
});

void it('should update a multiple properties in document in both PostgreSQL and MongoDB', async () => {
const pongoCollection = pongoDb.collection<User>('updateOneMultiple');
const mongoCollection = mongoDb.collection<User>('updateOneMultiple');
const doc = { name: 'Roger', age: 30 };

const pongoInsertResult = await pongoCollection.insertOne(doc);
const mongoInsertResult = await mongoCollection.insertOne(doc);

const update = { $set: { age: 31, tags: [] } };

await pongoCollection.updateOne(
{ _id: pongoInsertResult.insertedId },
update,
);
await mongoCollection.updateOne(
{ _id: mongoInsertResult.insertedId },
update,
);

const pongoDoc = await pongoCollection.findOne({
_id: pongoInsertResult.insertedId,
});
const mongoDoc = await mongoCollection.findOne({
_id: mongoInsertResult.insertedId,
});

assert.equal(mongoDoc?.age, 31);
assert.deepEqual(mongoDoc?.tags, []);
assert.deepStrictEqual(
{
name: pongoDoc!.name,
age: pongoDoc!.age,
tags: pongoDoc!.tags,
},
{
name: mongoDoc!.name,
age: mongoDoc!.age,
tags: mongoDoc!.tags,
},
);
});
Expand Down Expand Up @@ -218,11 +262,11 @@ void describe('MongoDB Compatibility Tests', () => {
assert.deepStrictEqual(
pongoDocs.map((doc) => ({
name: doc.name,
age: 31,
age: doc.age,
})),
mongoDocs.map((doc) => ({
name: doc.name,
age: 31,
age: doc.age,
})),
);
});
Expand All @@ -235,10 +279,11 @@ void describe('MongoDB Compatibility Tests', () => {
const pongoInsertResult = await pongoCollection.insertOne(doc);
const mongoInsertResult = await mongoCollection.insertOne(doc);

await pongoCollection.updateOne(
const { matchedCount } = await pongoCollection.updateOne(
{ _id: pongoInsertResult.insertedId },
{ $unset: { address: '' } },
);
assert.equal(matchedCount, 1);
await mongoCollection.updateOne(
{ _id: mongoInsertResult.insertedId },
{ $unset: { address: '' } },
Expand Down Expand Up @@ -275,10 +320,11 @@ void describe('MongoDB Compatibility Tests', () => {

const update = { $inc: { age: 1 } };

await pongoCollection.updateOne(
const { matchedCount } = await pongoCollection.updateOne(
{ _id: pongoInsertResult.insertedId },
update,
);
assert.equal(matchedCount, 1);
await mongoCollection.updateOne(
{ _id: mongoInsertResult.insertedId },
update,
Expand Down Expand Up @@ -306,21 +352,39 @@ void describe('MongoDB Compatibility Tests', () => {
void it('should update a document in both PostgreSQL and MongoDB using $push', async () => {
const pongoCollection = pongoDb.collection<User>('testCollection');
const mongoCollection = mongoDb.collection<User>('testCollection');
const doc = { name: 'Roger', age: 30, tags: ['tag1'] };
const doc = { name: 'Roger', age: 30 };

const pongoInsertResult = await pongoCollection.insertOne(doc);
const mongoInsertResult = await mongoCollection.insertOne(doc);
let pongoDoc = await pongoCollection.findOne({
_id: pongoInsertResult.insertedId,
});
// Push to non existing
let updateResult = await pongoCollection.updateOne(
{ _id: pongoInsertResult.insertedId },
{ $push: { tags: 'tag1' } },
);
assert.equal(updateResult.matchedCount, 1);
await mongoCollection.updateOne(
{ _id: mongoInsertResult.insertedId },
{ $push: { tags: 'tag1' } },
);
pongoDoc = await pongoCollection.findOne({
_id: pongoInsertResult.insertedId,
});

await pongoCollection.updateOne(
// Push to existing
updateResult = await pongoCollection.updateOne(
{ _id: pongoInsertResult.insertedId },
{ $push: { tags: 'tag2' } },
);
assert.equal(updateResult.matchedCount, 1);
await mongoCollection.updateOne(
{ _id: mongoInsertResult.insertedId },
{ $push: { tags: 'tag2' } },
);

const pongoDoc = await pongoCollection.findOne({
pongoDoc = await pongoCollection.findOne({
_id: pongoInsertResult.insertedId,
});
const mongoDoc = await mongoCollection.findOne({
Expand Down Expand Up @@ -351,7 +415,10 @@ void describe('MongoDB Compatibility Tests', () => {
const pongoInsertResult = await pongoCollection.insertOne(doc);
const mongoInsertResult = await mongoCollection.insertOne(doc);

await pongoCollection.deleteOne({ _id: pongoInsertResult.insertedId });
const { deletedCount } = await pongoCollection.deleteOne({
_id: pongoInsertResult.insertedId,
});
assert.equal(deletedCount, 1);
await mongoCollection.deleteOne({ _id: mongoInsertResult.insertedId });

const pongoDoc = await pongoCollection.findOne({
Expand Down Expand Up @@ -475,8 +542,12 @@ void describe('MongoDB Compatibility Tests', () => {
});

void it('should find documents with a nested property filter in both PostgreSQL and MongoDB', async () => {
const pongoCollection = pongoDb.collection<User>('testCollection');
const mongoCollection = mongoDb.collection<User>('testCollection');
const pongoCollection = pongoDb.collection<User>(
'findWithNestedProperty',
);
const mongoCollection = mongoDb.collection<User>(
'findWithNestedProperty',
);

const docs = [
{
Expand Down Expand Up @@ -522,8 +593,12 @@ void describe('MongoDB Compatibility Tests', () => {
});

void it('should find documents with multiple nested property filters in both PostgreSQL and MongoDB', async () => {
const pongoCollection = pongoDb.collection<User>('testCollection');
const mongoCollection = mongoDb.collection<User>('testCollection');
const pongoCollection = pongoDb.collection<User>(
'findWithMultipleNestedProperties',
);
const mongoCollection = mongoDb.collection<User>(
'findWithMultipleNestedProperties',
);

const docs = [
{
Expand Down Expand Up @@ -625,8 +700,8 @@ void describe('MongoDB Compatibility Tests', () => {
});

void it('should find documents with an array filter in both PostgreSQL and MongoDB', async () => {
const pongoCollection = pongoDb.collection<User>('testCollection');
const mongoCollection = mongoDb.collection<User>('testCollection');
const pongoCollection = pongoDb.collection<User>('findWithArrayFilter');
const mongoCollection = mongoDb.collection<User>('findWithArrayFilter');

const docs = [
{ name: 'Anita', age: 25, tags: ['tag1', 'tag2'] },
Expand All @@ -652,8 +727,12 @@ void describe('MongoDB Compatibility Tests', () => {
});

void it('should find documents with multiple array filters in both PostgreSQL and MongoDB', async () => {
const pongoCollection = pongoDb.collection<User>('testCollection');
const mongoCollection = mongoDb.collection<User>('testCollection');
const pongoCollection = pongoDb.collection<User>(
'findWithMultipleArrayFilters',
);
const mongoCollection = mongoDb.collection<User>(
'findWithMultipleArrayFilters',
);

const docs = [
{ name: 'Anita', age: 25, tags: ['tag1', 'tag2'] },
Expand Down Expand Up @@ -714,8 +793,12 @@ void describe('MongoDB Compatibility Tests', () => {
});

void it('should find documents with a nested array element match filter in both PostgreSQL and MongoDB', async () => {
const pongoCollection = pongoDb.collection<User>('testCollection');
const mongoCollection = mongoDb.collection<User>('testCollection');
const pongoCollection = pongoDb.collection<User>(
'findWithElemMatchFilter',
);
const mongoCollection = mongoDb.collection<User>(
'findWithElemMatchFilter',
);

const docs = [
{
Expand Down
22 changes: 12 additions & 10 deletions src/packages/pongo/src/postgres/update/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,27 @@ export const buildUpdateQuery = <T>(update: PongoUpdate<T>): SQL =>
}, sql('data'));

export const buildSetQuery = <T>(set: $set<T>, currentUpdateQuery: SQL): SQL =>
sql(
'jsonb_set(%s, %L, data || %L)',
currentUpdateQuery,
'{}',
JSON.stringify(set),
);
sql('%s || %L::jsonb', currentUpdateQuery, JSON.stringify(set));

export const buildUnsetQuery = <T>(
unset: $unset<T>,
currentUpdateQuery: SQL,
): SQL => sql('%s - %L', currentUpdateQuery, Object.keys(unset).join(', '));
): SQL =>
sql(
'%s - %L',
currentUpdateQuery,
Object.keys(unset)
.map((k) => `{${k}}`)
.join(', '),
);

export const buildIncQuery = <T>(
inc: $inc<T>,
currentUpdateQuery: SQL,
): SQL => {
for (const [key, value] of Object.entries(inc)) {
currentUpdateQuery = sql(
"jsonb_set(%s, '{%s}', to_jsonb((data->>'%s')::numeric + %L))",
"jsonb_set(%s, '{%s}', to_jsonb((data->>'%s')::numeric + %L), true)",
currentUpdateQuery,
key,
key,
Expand All @@ -53,11 +55,11 @@ export const buildPushQuery = <T>(
): SQL => {
for (const [key, value] of Object.entries(push)) {
currentUpdateQuery = sql(
"jsonb_set(%s, '{%s}', (COALESCE(data->'%s', '[]'::jsonb) || '[%s]'::jsonb))",
"jsonb_set(%s, '{%s}', (coalesce(data->'%s', '[]'::jsonb) || %L::jsonb), true)",
currentUpdateQuery,
key,
key,
JSON.stringify(value),
JSON.stringify([value]),
);
}
return currentUpdateQuery;
Expand Down

0 comments on commit 5c80a7f

Please sign in to comment.