skip to Main Content

I recently upgraded from Mongoose 5.x to 8.x and one of my queries that previously worked is no longer returning any documents, and nothing in the migration guides seemed to indicate why that would be the case.

Here is a reduced/simplified example of one of the collection items from our fixture data:

{
    _id: ObjectId('5ff8c2dd6b59a6000d7bfdb2'),
    __t: 'Item',
    name: 'Item Name',
    tags: {
      tag1: [
        'option1',
        'option2',
        'option3',
      ],
      tag2: [
        'option1',
      ],
    },
  },
 

My query looks something like this:

{"$and":[{"$and":[{"tags.tag1":["option2"]},{"tags.tag2":["option1"]}]}

In Mongoose 5.x, the fixture document above would be returned from this query. However in 8.x, it is not. I tested a bunch of things and it turns out if I were to remove option1 and option3 such that the new tags object looked like this:

tags: {
      tag1: [
        'option2',
      ],
      tag2: [
        'option1',
      ],
    },

then the item does get returned from the query. This seems to indicate that it will only be returned if the tag1 array matches the query exactly, rather than simply containing the item requested.

How would one ask Mongoose to return the document if the tag1 array includes option2, even if there are other tags in the array?

4

Answers


  1. Use $setIsSubset for comparison of 2 arrays.

    db.collection.find({
      "$expr": {
        "$and": [
          {
            "$setIsSubset": [
              [
                "option2"
              ],
              "$tags.tag1"
            ]
          },
          {
            "$setIsSubset": [
              [
                "option1"
              ],
              "$tags.tag2"
            ]
          }
        ]
      }
    })
    

    Mongo Playground

    Login or Signup to reply.
  2. The issue is with the given values – [“option2”] and [“option1”].

    In this case, it should be simply string values like “option2” and “option1”.

    The modified query would be like this:

    t.issue.find({"$and":[{"$and":[{"tags.tag1":"option2"},{"tags.tag2":"option1"}]}]})
    
    OUTPUT:
    [
      {
        _id: ObjectId('5ff8c2dd6b59a6000d7bfdb2'),
        __t: 'Item',
        name: 'Item Name',
        tags: { tag1: [ 'option1', 'option2', 'option3' ], tag2: [ 'option1' ] }
      }
    ]
    
    Login or Signup to reply.
  3. This is a detailed answer to the question. There is a short answer already posted separately. Request you may please start from there and proceed with this if not doing so.

    There are two things to note – array match and value match. The following action log will demonstrate it.

    use test
    test> t = db.test
    test> t.drop();
    
    test> t.insertOne({a:[1]});
    
    // open query
    test> t.find();
    [ { a: [ 1 ] } ]
    
    // below query finds the document by an exact match or an array match
    test> t.find({a: [1] });
    [ { a: [ 1 ] } ]
    
    // below query finds the document by a value match
    test> t.find({a:1});
    [ { a: [ 1 ] } ]
    
    // note that the array now has two items by the following query
    test> t.updateOne({},{$push:{a:2}});
    test> t.find();
    [ { a: [ 1, 2 ] } ]
    
    
    // below query still finds the document by a value match
    test> t.find({a:1});
    [ { a: [ 1, 2 ] } ]
    
    // below query does not find the document by an exact match or array match since [1 ] not equal to [1, 2]
    test> t.find({a:[1]});
    <no documents>
    
    // below query does find the document by an exact match or a array match since [1,2 ]  equal to [1, 2]
    test> t.find({a:[1,2]});
    [ { a: [ 1, 2 ] } ]
    
    // below query does not find the document by an exact match or a array match since [2,1 ] not equal to [1, 2]
    test> t.find({a:[1,2]});
    [ { a: [ 1, 2 ] } ]
    
    Login or Signup to reply.
  4. $in operator is used to perform match a single value against array

    As mentioned above please try executing query as mentioned in following link
    https://mongoplayground.net/p/RQx2MJFivIK

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search