Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.cursor({ transform: JSON.stringify }) doesn't work the same way for AggregationCursor as in QueryCursor (when piped to response) #14331

Closed
2 tasks done
kemalcany opened this issue Feb 2, 2024 · 1 comment · Fixed by #14348
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@kemalcany
Copy link

kemalcany commented Feb 2, 2024

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

8.1.1

Node.js version

18.13.0

MongoDB server version

6.0.4

Typescript version (if applicable)

5.3.3

Description

The { transform: JSON.stringify } option for a cursor doesn't produce the expected result on aggregation cursors while they work fine with query cursors.

The example below with .find() works well and you can get the streamed documents on the client

@Get('apples')
async getApplesWithQuery(@Response() res) {
   Fruit.find({name:"Apple"}).cursor({ transform: JSON.stringify }).pipe(res.type('json'))
}

Whereas the same request (below) with aggregation/$match doesn't work and you get an error like the one at the bottom:

@Get('apples')
async getApplesWithAggregation(@Response() res) {
   Fruit.aggregate([{$match:{name:"Apple"})}]).cursor({ transform: JSON.stringify }).pipe(res.type('json'))
}
TypeError: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Object
    at new NodeError (node:internal/errors:400:5)
    at write_ (node:_http_outgoing:862:11)
    at ServerResponse.write (node:_http_outgoing:827:15)
    at AggregationCursor.ondata (node:internal/streams/readable:766:22)
    at AggregationCursor.emit (node:events:513:28)
    at addChunk (node:internal/streams/readable:324:12)
    at readableAddChunk (node:internal/streams/readable:297:9)
    at AggregationCursor.Readable.push (node:internal/streams/readable:234:10)
    at /XXX/node_modules/.pnpm/mongoose@8.1.1/node_modules/mongoose/lib/cursor/aggregationCursor.js:96:11
    at /XXX/node_modules/.pnpm/mongoose@8.1.1/node_modules/mongoose/lib/cursor/aggregationCursor.js:375:

Steps to Reproduce

Replacing a find query with $match aggregation on a cursor response can demonstrate the issue.

Note that the aggregation cursor works well. ie if you do simply read the cursor with .next(), you can get the values fine. The issue happens when you try to pipe it as a response due to the fact that the results are not getting JSON.stringified as they would on a query cursor

Expected Behavior

No response

Tasks

No tasks being tracked yet.
@vkarpov15 vkarpov15 added this to the 8.1.3 milestone Feb 7, 2024
@IslandRhythms IslandRhythms added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Feb 9, 2024
@IslandRhythms
Copy link
Collaborator

const mongoose = require('mongoose');
const { Writable } = require('stream')
const testSchema = new mongoose.Schema({
  name: String
});

const Test = mongoose.model('Test', testSchema);

async function run() {
  await mongoose.connect('mongodb://localhost:27017');
  await mongoose.connection.dropDatabase();

  for(let i = 0; i < 11; i++) {
    await Test.create({ name: 'Apple' });
  }
  for(let i = 0; i < 11; i++) {
    await Test.create({ name: 'Orange'})
  }

  const writableStream = new Writable({
    write(chunk, encoding, callback) {
      console.log(chunk.toString()); // Log the chunk to the console
      callback(); // Call the callback to indicate that processing is complete
    }
  });

  const otherStream = new Writable({
    write(chunk, encoding, callback) {
      console.log(chunk.toString()); // Log the chunk to the console
      callback(); // Call the callback to indicate that processing is complete
    }
  });

  console.log('find');
  await Test.find({ name: 'Apple' }).cursor({ transform: JSON.stringify }).pipe(writableStream);
  console.log('aggregate');
  await Test.aggregate([{$match: { name: 'Orange' }}]).cursor({ transform: JSON.stringify }).pipe(otherStream);

  console.log('done');
}

run();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
3 participants