简体   繁体   English

根据条件在MongoDB中进行投影

[英]Projection in MongoDB based on Conditions

My document structure in c#: 我在C#中的文档结构:

 public class HashTableDocument : Model
    {
        public int Id { get; set; }
        public Dictionary<string, HashSet<int>> items= new Dictionary<string, HashSet<int>>();
    }

in Mongo: 在蒙哥:

{
    "_id" : 218,
    "items" : {
        "1" : [ 
            52711, 
            201610, 

        ],
        "2" : [ 
            246421, 
            390200
        ],
        "3" : [ 
            105628, 
            768519
        ],
        "26" : [ 
            17435, 
            22252, 
            61389, 
            65184, 
            72859, 
            81421, 
            931469, 
            933505, 
            938377, 
            959836
        ],
        "27" : [ 
            26917, 
            38706, 
            53862, 
            111816, 
            827294, 
            858348, 
            870334
        ]
    }
}

I want to be able to pass in any List ('x') of Integers to Mongo. 我希望能够将任何整数列表('x')传递给Mongo。 And project on only those key value pairs, if values contains any of the integer in given list ('x'). 如果值包含给定列表('x')中的任何整数,则仅对那些键值对进行投影。

For example, in above document. 例如,在上述文件中。 if i pass List = { 52711, 105628, 17435, 81421} to Mongo then It should return 如果我将List = { 52711, 105628, 17435, 81421}传递给Mongo,则应该返回

{
    "_id" : 218,
    "items" : {
        "1" : [ 
            52711, 
            201610, 

        ],
        "3" : [ 
            105628, 
            768519
        ],
        "26" : [ 
            17435, 
            22252, 
            61389, 
            65184, 
            72859, 
            81421, 
            931469, 
            933505, 
            938377, 
            959836
        ],
     }
}

because each one of those key's value contains at least one element in it's list. 因为这些键的值中的每一个在其列表中至少包含一个元素

I don't know the C# syntax, but here's how to do it using the aggregation framework. 我不知道C#语法,但是下面是使用聚合框架的方法。 Note that this uses the $objectToArray expression, introduced in version 3.4.4. 请注意,这使用版本3.4.4中引入的$objectToArray表达式。

> db.test.aggregate([{
  $project: {
    x: {
      $filter: {
        input: {$objectToArray: "$items"},
        cond: {
          $gt: [
            {
              $size: {
                $filter: {
                  input: "$$this.v",
                  as: "int",
                  cond: {$in: ["$$int", [52711, 105628, 17435, 81421]]}
                }
              }
            },
            0
          ]
        }
      }
    }
  }
}])
{
  "result": [
    {
      "_id": 218,
      "items": [
        {
          "k": "1",
          "v": [
            52711,
            201610
          ]
        },
        {
          "k": "3",
          "v": [
            105628,
            768519
          ]
        },
        {
          "k": "26",
          "v": [
            17435,
            22252,
            61389,
            65184,
            72859,
            81421,
            931469,
            933505,
            938377,
            959836
          ]
        }
      ]
    }
  ],
  "ok": 1
}

However, it's generally not easy to do such computation when you have a structure like you do. 但是,当您拥有类似的结构时,进行这样的计算通常并不容易。 This aggregation cannot use any indexes to restrict its search. 此聚合不能使用任何索引来限制其搜索。 Have you considered using the following schema instead? 您是否考虑过使用以下架构?

{
  "_id": 218,
  "items": [
    {k: "1", v: [52711, 201610]},
    {k: "2", v: [246421, 390200]},
    {k: "3", v: [105628, 768519]},
    {k: "26", v: [17435, 22252, 61389, 65184, 72859, 81421, 931469, 933505, 938377, 959836]},
    {k: "27", v: [26917, 38706, 53862, 111816, 827294, 858348, 870334]},
  ]
}

Then your problem becomes much simpler, and you can do the following instead: 然后,您的问题变得简单得多,您可以改为执行以下操作:

db.test.aggregate([
  {$match: {"items.v": {$in: [52711, 105628, 17435, 81421]}}},
  {
    $project: {
      items: {
        $filter: {
          input: "$items",
          cond: {
            $size: {
              $setIntersection:
                  [[52711, 105628, 17435, 81421], "$$this.v"]
            }
          }
        }
      }
    }
  }
])

And if you created an index on the field "items.v", the initial $match stage could leverage that index to do a more efficient query. 而且,如果您在“ items.v”字段上创建了索引,则初始$match阶段可以利用该索引来执行更有效的查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM