2017-04-19 64 views
0

我的文檔結構在C#:投影MongoDB中根據具體的情況

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

{ 
    "_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 
     ] 
    } 
} 

我希望能夠在任何整數列表( 'X')來傳遞蒙戈。如果值包含給定列表('x')中的任何整數,則僅對這些鍵值對進行投影。

例如,在上面的文檔中。如果我通過List = { 52711, 105628, 17435, 81421}到蒙戈然後 它應該返回

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

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

,因爲這些鍵的值的每一個包含至少一個元素在它的列表中。

回答

2

我不知道C#語法,但下面是如何使用聚合框架來完成它。請注意,這使用了版本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 
} 

然而,當你有像你這樣的結構時,做這樣的計算通常是不容易的。此聚合不能使用任何索引來限制其搜索。你有沒有考慮過使用下面的模式呢?

{ 
    "_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]}, 
    ] 
} 

那麼你的問題就變得簡單多了,你可以做,而不是執行以下操作:

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"] 
      } 
      } 
     } 
     } 
    } 
    } 
]) 

如果你在球場上「items.v」創建索引,初始階段$match可以利用該索引可以執行更高效的查詢。