在深度嵌套的文档查询中使用MongoDB的位置运算符$ [英] Using MongoDB's positional operator $ in a deeply nested document query

查看:76
本文介绍了在深度嵌套的文档查询中使用MongoDB的位置运算符$的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以将位置运算符'$'与深度嵌套的文档数组上的查询结合使用?

Is it possible to use positional operator '$' in combination with a query on a deeply-nested document array?

考虑以下定义用户"的嵌套文档:

Consider the following nested document defining a 'user':

{
   username: 'test',
   kingdoms: [

      {
          buildings: [

              {
                  type: 'castle'

              },
              {
                  type: 'treasury'
              },

              ...

          ]

      },

      ...

   ] 
}

我们想返回特定用户的城堡",例如形式:

We'd like to return the 'castles' for a particular user e.g. in a form:

{
    kingdoms: [{

        buildings: [{

            type: 'castle'

        }]

    }]
}

因为您不能两次使用$运算符( https://jira.mongodb.org/Browse/server-831 ),我知道我也无法查询特定的王国,所以我正在尝试为第n个王国编写查找语句.

Because you cannot use the $ operator twice (https://jira.mongodb.org/browse/server-831) I know that I can't also query for a particular kingdom, so I'm trying to write a find statement for the nth kingdom.

当更新深度嵌套的子文档时,这似乎很有意义( Mongodb更新深度嵌套子文档),但查找查询的成功率较低.

This seems to make sense when updating a deeply-nested sub-document (Mongodb update deeply nested subdocument) but I'm having less success with the find query.

我可以使用查询返回第一个王国的建筑物:

I can return the first kingdom's buildings with the query:

db.users.findOne(
    { username: 'test' },
    { kingdoms: {$slice: [0, 1]}, 'kingdom.buildings': 1 }
);

但这会返回该王国的所有建筑物.

But this returns all the buildings of that kingdom.

下面是位置运算符的单层示例,我正在尝试这样的查询:

Following the single-level examples of position operator I'm trying a query like this:

db.users.findOne(
    { username: 'test', 'kingdoms.buildings.type': 'castle' },
    { kingdoms: {$slice: [n, 1]}, 'kingdom.buildings.$': 1 }
);

以这样的形式:

db.collection.find( { <array.field>: <value> ...}, { "<array>.$": 1 } ) 

如文档 http://docs中所述.mongodb.org/manual/reference/operator/projection/positional/#proj. S

但是,此操作因错误而失败:

However this fails with the error:

Positional operator does not match the query specifier

大概是因为Kingdoms.buildings不被视为数组.我也尝试过 kingdoms.0.buildings

Presumably because kingdoms.buildings isn't considered an array. I've also tried kingdoms.0.buildings

这令人困惑,因为它似乎可以用于更新(根据 Mongodb更新深度嵌套的子文档)

It is confusing because this appears to work for updates (according to Mongodb update deeply nested subdocument)

我只是语法错误,还是不支持此语法?如果是这样,有没有办法实现类似的目标?

Have I just got the syntax wrong or is this not supported? If so is there a way to achieve something similar?

推荐答案

您从

db.users.findOne(
    { username: 'test', 'kingdoms.buildings.type': 'castle' },
    { kingdoms: {$slice: [n, 1]}, 'kingdom.buildings.$': 1 }
);

因为存在拼写错误("kingdom.buildings.$"应为"kingdom s .buildings.$").
但是,这种方式无法实现您的期望.
$ 始终以 kingdoms.buildings 的路径(第一个数组)为目标王国.

because there is a spelling mistake ("kingdom.buildings.$" should be "kingdoms.buildings.$").
However, this way can not accomplish what you expect.
$ is always aimed at kingdoms in the path of kingdoms.buildings - the first array.

这是应该能够解决问题的方法.
(需要V2.6 +)

This is a way that should be able to solve the problem.
(V2.6+ required)

db.c.aggregate([ {
    $match : {
        username : 'test',
        'kingdoms.buildings.type' : 'castle'
    }
}, {
    $project : {
        _id : 0,
        kingdoms : 1
    }
}, {
    $redact : {
        $cond : {
            "if" : {
                $or : [ {
                    $gt : [ "$kingdoms", [] ]
                }, {
                    $gt : [ "$buildings", [] ]
                }, {
                    $eq : [ "$type", "castle" ]
                } ]
            },
            "then" : "$$DESCEND",
            "else" : "$$PRUNE"
        }
    }
} ]).pretty();


仅保留王国的第一个元素,


To only reserve the first element of kingdoms,

db.c.aggregate([ {
    $match : {
        username : 'test',
        'kingdoms.buildings.type' : 'castle'
    }
}, {
    $redact : {
        $cond : {
            "if" : {
                $or : [ {
                    $gt : [ "$kingdoms", [] ]
                }, {
                    $gt : [ "$buildings", [] ]
                }, {
                    $eq : [ "$type", "castle" ]
                } ]
            },
            "then" : "$$DESCEND",
            "else" : "$$PRUNE"
        }
    }
}, {
    $unwind : "$kingdoms"
}, {
    $group : {
        _id : "$_id",
        kingdom : {
            $first : "$kingdoms"
        }
    }
}, {
    $group : {
        _id : "$_id",
        kingdoms : {
            $push : "$kingdom"
        }
    }
}, {
    $project : {
        _id : 0,
        kingdoms : 1
    }
} ]).pretty();

这篇关于在深度嵌套的文档查询中使用MongoDB的位置运算符$的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆