Mongodb find()只包含非空数组

Mongodb find() only include non-empty arrays

本文关键字:包含非 数组 find Mongodb      更新时间:2023-09-26

我想用查找查询实现的是只包括"someArray"s,如果它的内部数组不是空的。例如下面的JSON:

{
  "document": "some document",
  "someArray": [
    {
      "innerArray": [
        "not empty"
      ]
    },
    {
      "innerArray": [
        [] //empty
      ]
    }
  ]
}

将返回这个:

{
  "document": "some document",
  "someArray": [
    {
      "innerArray": [
        "not empty"
      ]
    }
  ]
}

我使用以下查找:

Visit.find({'someArray.innerArray.0': {$exists: true}}, function(err, data){});

但是,这会返回所有的数据。

也试过了:

Visit.find({}, {'someArray.innerArray': {$gt: 0}}, function(err, data) {});

但是这没有返回任何

对于如何处理这个问题有什么想法吗?

欢呼

这里检查非空数组的一般情况是检查"first"元素是否实际存在。对于单个匹配,您可以使用位置$运算符进行投影:

Vist.find(
    { "someArray.innerArray.0": { "$exists": true } },
    { "document": 1,"someArray.$": 1},
    function(err,data) {
    }
);

如果你需要不止一个匹配,或者数组嵌套得比这更深,那么聚合框架就是你需要处理更难的投影和/或"过滤"多个匹配的数组结果的工具:

Visit.aggregate(
    [
        // Match documents that "contain" the match
        { "$match": {
            "someArray.innerArray.0": { "$exists": true }
        }},
        // Unwind the array documents
        { "$unwind": "$someArray" },
        // Match the array documents
        { "$match": {
            "someArray.innerArray.0": { "$exists": true }
        }},
        // Group back to form
        { "$group": {
            "_id": "$_id",
            "document": { "$first": "$document" },
            "someArray": { "$push": "$someArray" }
        }}
    ],function(err,data) {

    }
)

这里值得注意的是,你把它称为"空",但实际上它不是,因为它实际上包含另一个空数组。您可能不希望对实际数据这样做,但如果有的话,您需要这样过滤:

Visit.aggregate(
    [
        { "$match": {
            "someArray": { "$elemMatch": { "innerArray.0": { "$ne": [] } } }
        }},
        { "$unwind": "$someArray" },
        { "$match": {
            "someArray.innerArray.0": { "$ne": [] }
        }},
        { "$group": {
            "_id": "$_id",
            "document": { "$first": "$document" },
            "someArray": { "$push": "$someArray" }
        }}
     ],function(err,data) {

     }
);