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

Incorrect query translation with $elemMatch and $or in Mongoose 8.x #15081

Open
2 tasks done
GalZen opened this issue Dec 8, 2024 · 2 comments
Open
2 tasks done

Incorrect query translation with $elemMatch and $or in Mongoose 8.x #15081

GalZen opened this issue Dec 8, 2024 · 2 comments
Labels
can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. Stale

Comments

@GalZen
Copy link

GalZen commented Dec 8, 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.8.3

Node.js version

16.20.1

MongoDB server version

7.0

Typescript version (if applicable)

4.6.3

Description

I encountered a bug where a query using .elemMatch() with $or conditions is not translated correctly by Mongoose.

Steps to Reproduce

Run the following query

{
"sharedWith": {
"$elemMatch": {
"$or": [
{ "targetType": "user", "targetId": "someId", "isShared": true },
{ "targetType": "role", "targetId": { "$in": ["role1", "role2"] }, "isShared": true }
]
}
}
}

the query it translated to the following:
The query is translated to:

{
"sharedWith": {
"$ne": { "targetType": "user", "targetId": "someId", "isShared": false },
"$elemMatch": {
"$or": [ {}, {} ]
}
}
}

Expected Behavior

userdataitemslist.find(
{
user: { $ne: ObjectId("6755824f6f0da222862ad889") },
client: ObjectId("6755824f6f0da222862ad855"),
sharedWith: {
$ne: {
targetType: "user",
targetId: "6755824f6f0da222862ad889",
isShared: false
},
$elemMatch: {
$or: [
{
targetType: "user",
targetId: "6755824f6f0da222862ad889",
isShared: true
},
{
targetType: "role",
targetId: { $in: ["admin"] },
isShared: true
}
]
}
}
}

@vkarpov15
Copy link
Collaborator

I'm unable to repro, the following script shows that Mongoose correctly casts $or within $elemMatch: it correctly casts targetId to an ObjectId, so the query returns the sample document. Please modify the following script to demonstrate the issue you're seeing.

const mongoose = require('mongoose');
mongoose.set('debug', true);
    
// Define the schema and model
const UserDataItemSchema = new mongoose.Schema({
  user: mongoose.Schema.Types.ObjectId,
  client: mongoose.Schema.Types.ObjectId,
  sharedWith: [
    { 
      targetType: String,
      targetId: String,
      isShared: Boolean,
    },
  ],
}); 
      
const UserDataItem = mongoose.model('UserDataItem', UserDataItemSchema);

(async () => {
  // Connect to MongoDB
  await mongoose.connect('mongodb://localhost:27017/test');
          
  console.log('Connected to MongoDB');
            
  // Clear the collection for a clean slate 
  await UserDataItem.deleteMany({});
          
  // Insert sample data
  await UserDataItem.create([
    {
      user: new mongoose.Types.ObjectId('6755824f6f0da222862ad889'),
      client: new mongoose.Types.ObjectId('6755824f6f0da222862ad855'),
      sharedWith: [
        { targetType: 'user', targetId: '6755824f6f0da222862ad889', isShared: true },
        { targetType: 'role', targetId: 'admin', isShared: true },
      ],
    },
  ]);

  // Define the problematic query
  const query = {
    sharedWith: {
      $elemMatch: {
        $or: [
          {
            targetType: 'user',
            targetId: '6755824f6f0da222862ad889',
            isShared: true,
          },
          {
            targetType: 'role',
            targetId: { $in: ['superadmin'] },
            isShared: true,
          },
        ],
      },
    },
  };

  // Execute the query
  const results = await UserDataItem.find(query);
  console.log('Query Results:', results);
})();

Output:

$ node gh-15081.js 
Connected to MongoDB
Mongoose: userdataitems.deleteMany({}, {})
Mongoose: userdataitems.insertOne({ user: ObjectId("6755824f6f0da222862ad889"), client: ObjectId("6755824f6f0da222862ad855"), sharedWith: [ { targetType: 'user', targetId: '6755824f6f0da222862ad889', isShared: true, _id: ObjectId("675f36e0115f0f035ad8746b") }, { targetType: 'role', targetId: 'admin', isShared: true, _id: ObjectId("675f36e0115f0f035ad8746c") } ], _id: ObjectId("675f36e0115f0f035ad8746a"), __v: 0}, {})
Mongoose: userdataitems.find({ sharedWith: { '$elemMatch': { '$or': [ { targetType: 'user', targetId: '6755824f6f0da222862ad889', isShared: true }, { targetType: 'role', targetId: { '$in': [ 'superadmin' ] }, isShared: true } ] } }}, {})
Query Results: [
  {
    _id: new ObjectId('675f36e0115f0f035ad8746a'),
    user: new ObjectId('6755824f6f0da222862ad889'),
    client: new ObjectId('6755824f6f0da222862ad855'),
    sharedWith: [ [Object], [Object] ],
    __v: 0
  }
]

@vkarpov15 vkarpov15 added the can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. label Dec 15, 2024
Copy link

This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days

@github-actions github-actions bot added the Stale label Dec 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. Stale
Projects
None yet
Development

No branches or pull requests

2 participants