1

I'm trying to retrieve documents where the tags array does not contain an element ignoring case sensitivity.

I'm using the inverse of my array contains query:

.find({"tags":{"$regex": "^(?!someTag$)", "$options": "i"}})

However this returns also returns documents where there's a tag that isn't "someTag".

Viktor Baert
  • 686
  • 8
  • 22

2 Answers2

1

Answer provided by a colleague:

Adding a simple $not does the trick.

.find({"tags": {"$not": {"$regex": "^(?!someTag$)", "$options": "i"}}},{"tags":1})
Viktor Baert
  • 686
  • 8
  • 22
0

You can get array does not include behavior with the not equal $ne operator, and case insensitivity with a collation.

Consider a collection with several tags:

> db.coll.find({},{_id:0})
{ "tags" : [ "Tag1", "Tag2", "Tag3" ] }
{ "tags" : [ "tag1", "tag2", "tag3" ] }
{ "tags" : [ "TAG4", "TAG3", "TAG5" ] }
{ "tags" : [ "tag4", "tag6", "tag7" ] }

$ne can be used to exclude exact matches:

> db.coll.find({tags:{$ne:"tag3"}},{_id:0})
{ "tags" : [ "Tag1", "Tag2", "Tag3" ] }
{ "tags" : [ "TAG4", "TAG3", "TAG5" ] }
{ "tags" : [ "tag4", "tag6", "tag7" ] }

With the addition of a collation, the $ne match can be case insensitive:

> db.coll.find({tags:{$ne:"tag3"}},{_id:0}).collation({locale:"en",strength:1})
{ "tags" : [ "tag4", "tag6", "tag7" ] }

Note that in order to use an index with this query, you will need to create an appropriate index with the same collation.

Joe
  • 25,000
  • 3
  • 22
  • 44