$in requires an array as a second argument, found:

2019-01-20 13:33发布

问题:

can anybody please tell me what am i doing wrong?

db document structure:

{
    "_id" : "module_settings",
    "moduleChildren" : [
        {
            "_id" : "module_settings_general",
            "name" : "General",
        },
        {
            "_id" : "module_settings_users",
            "name" : "Users",
        },
        {
            "_id" : "module_settings_emails",
            "name" : "Emails",
        }
    ],
    “permissions” : [
        "module_settings_general",
        "module_settings_emails"
    ]
}

pipeline stage:

{ $project: {
    filteredChildren: {
        $filter: {
           input: "$moduleChildren",
           as: "moduleChild",
           cond: { $in : ["$$moduleChild._id", "$permissions"] }
        }
    },
}}

I need to filter "moduleChildren" array to show only modules which ids are in "permissions" array. Ive tried "$$ROOT.permissions" and "$$CURRENT.permissions" but none of them is working. I always get an error that $in is missing array as argument. It works when i hardcode the array like this: cond: { $in : ["$$moduleChild._id", [“module_settings_general", "module_settings_emails”]] } so it seems the problem is in passing of the array. Thanks for any advices!

回答1:

First option --> Use aggregation

Because your some of the documents in your collection may or may not contain permissions field or is type not equal to array that's why you are getting this error.

You can find the $type of the field and if it is not an array or not exists in your document than you can add it as an array with $addFields and $cond aggregation

db.collection.aggregate([
  { "$addFields": {
    "permissions": {
      "$cond": {
        "if": {
          "$ne": [ { "$type": "$permissions" }, "array" ]
        },
        "then": [],
        "else": "$permissions"
      }
    }
  }},
  { "$project": {
    "filteredChildren": {
      "$filter": {
        "input": "$moduleChildren",
        "as": "moduleChild",
        "cond": {
          "$in": [ "$$moduleChild._id", "$permissions" ]
        }
      }
    }
  }}
])

Second option -->

Go to your mongo shell or robomongo on any GUI you are using and run this command

db.collection.update(
  { "permissions": { "$type": { "$ne": "array" } } },
  { "$set": { "permissions": [] } },
  { "multi": true }
)