Skip to content

db.find({somefield:{$exists:true}}) returns all docs, but no doc contains the somefield! #11807

Closed
@creedofcool

Description

@creedofcool

mongoos 6.3.3
mongodb 4.2
express 5.0 beta

why?

Activity

added
helpThis issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary
on May 14, 2022
creedofcool

creedofcool commented on May 15, 2022

@creedofcool
Author

not happen at mongose@5.13.14 and 4.x
so is it a bug?

AbdelrahmanHafez

AbdelrahmanHafez commented on May 15, 2022

@AbdelrahmanHafez
Collaborator

Is it possible that the field has the value of null in your database? Because setting the value to null/undefined is not the same as $unsetting it.
If not, can you please modify the script below to reproduce the issue you're facing?

11807.js

'use strict';
import mongoose from 'mongoose';
const { Schema } = mongoose;
import assert from 'node:assert';


await mongoose.connect('mongodb://localhost:27017/test');
await mongoose.connection.dropDatabase();

const userSchema = new Schema({
  name: { type: String },
  age: Number
});

const User = mongoose.model('User', userSchema);
await User.insertMany([{ name: 'John' }, { name: 'Doe' }, { name: 'Jane', age: null }]);

const foundUsers = await User.find({ age: { $exists: true } });

// Jane is found, because you can set a field as `null`, and counts as a field
assert.ok(foundUsers.length === 1);

console.log(mongoose.version);
console.log('All assertions passed.');

Output:

$ node 11807.js
6.3.2
All assertions passed.
creedofcool

creedofcool commented on May 17, 2022

@creedofcool
Author
const mongoose = require("mongoose");
const { Schema } = mongoose;

const start = async () => {
  const mongodb_uri = "mongodb://localhost:38517/orm";
  await mongoose.connect(mongodb_uri);
  const userSchema = new Schema({
    name: { type: String, unique:true },
    age: Number,
  });
  const testUser = mongoose.model("testUser", userSchema);
  await testUser.insertMany([
    { name: "John" },
    { name: "Doe" },
    { name: "Jane", age: null },
  ]);

  const foundUsers = await testUser.find({ username: { $exists: true } });
  console.log(foundUsers);

  console.log(\`node version: ${process.version} && mongoose version: ${mongoose.version}\` );

  process.exit(1);
};

start();

output:
[ { _id: new ObjectId("6283441e619ff0529bcaf97d"), name: 'John', __v: 0 }, { _id: new ObjectId("6283441e619ff0529bcaf97e"), name: 'Doe', __v: 0 }, { _id: new ObjectId("6283441e619ff0529bcaf97f"), name: 'Jane', age: null, __v: 0 } ] node version: v16.2.0 && mongoose version: 6.3.2

Thank you @AbdelrahmanHafez
If change the search field to username which is not included in any doc, the result is all docs. I don't understand the logic.

Uzlopak

Uzlopak commented on May 17, 2022

@Uzlopak
Collaborator

There is no field username in your Schema.

AbdelrahmanHafez

AbdelrahmanHafez commented on May 17, 2022

@AbdelrahmanHafez
Collaborator

@creedofcool
You do not have a username field in your schema, so mongoose removes it from the filter. You can change this behavior by using strictQuery: false

const foundUsers = await testUser.find({ username: { $exists: true } }, null, { strictQuery: false });

You can also set this option globally:

mongoose.set('strictQuery', false); 

// or on a single schema level
schema.set('strictQuery', false);

Does that solve your problem?

creedofcool

creedofcool commented on May 18, 2022

@creedofcool
Author

Yes,
That's right, so awesome.
Thank you so much. @AbdelrahmanHafez

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    helpThis issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @Uzlopak@AbdelrahmanHafez@creedofcool

        Issue actions

          db.find({somefield:{$exists:true}}) returns all docs, but no doc contains the somefield! · Issue #11807 · Automattic/mongoose