如何在 MongoDB $projection 管道中使用 array.indexOf 中的变量名

How to use variable name in array.indexOf in MongoDB $projection pipeline

我有一个 collection 喜欢

   {
        "LifeTime" : 123.000,
        "Host" : "xxx.com",
    }, 
    {
        "LifeTime" : 213.000,
        "Host" : "yyy.com",
    }, 
    {
        "LifeTime" : 321.000,
        "Host" : "zzz.com",

    } 

和预定义的数组,如

["xxx.com","yyy.com"]

现在我想使用 $let & $cond 进行投影,这样如果数组中存在主机,则 LifeTime 将为 0,否则与 LifeTime 相同。

我试过了

LifeTime: {
    $let: {
    vars: {
        hostname: '$Host'
    },
    in: {
        "$cond": [
            {
                "$and": [
                    {
                        "$gte": [
                            ArrayOfPredefinedHost.indexOf('$$hostname'),
                            0
                        ]
                    }
                ]
            },
            0,
            "$LifeTime"
        ]
    }
    }
}

但它没有返回预期的结果。我认为 indexOf 试图找到 $$hostname 而不是 xxx.com,yyy.com & zzz.com

我该如何进行这种复杂的查询?

以下聚合管道将首先对文档进行分组,以允许包含使用 $addToSet accumulator operator. This additional field will then be used in the next $project pipeline stage in the $cond expression, taking advantage of the $setIsSubset 运算符的单个主机元素的附加数组字段:

var ArrayOfPredefinedHost = ["xxx.com", "yyy.com"];
db.collection.aggregate([
    {
        "$group": {
            "_id": {
                "id": "$_id",
                "LifeTime": "$LifeTime",
                "Host": "$Host"
            },
            "HostSet": { "$addToSet": "$Host" }
        }
    },
    {
        "$project": {
            "_id": 0,
            "LifeTime": {
                "$cond": [ { "$setIsSubset": [ "$HostSet", ArrayOfPredefinedHost ] }, "$_id.LifeTime", 0]
            },
            "Host": "$_id.Host"
        }
    }
]);

输出:

/* 0 */
{
    "result" : [ 
        {
            "LifeTime" : 0,
            "Host" : "zzz.com"
        }, 
        {
            "LifeTime" : 213,
            "Host" : "yyy.com"
        }, 
        {
            "LifeTime" : 123,
            "Host" : "xxx.com"
        }
    ],
    "ok" : 1
}