Mongo 聚合与 Java 循环和性能

Mongo aggregation vs Java for loop and performance

我存储了以下 mongo 文档

{
 "Field1": "ABC",
 "Field2": [
    { "Field3": "ABC1","Field4": [ {"id": "123" }, { "id" : "234" }, { "id":"345" }] }, 
    { "Field3": "ABC2","Field4": [ {"id": "123" }, { "id" : "234" }, { "id":"345" }] }, 
    { "Field3": "ABC3","Field4": [{ "id":"345" }] },  
    ]
}

从上面,我想获取 ID 为“123”的子文档

即。

{ 
    "Field3" : "ABC1",
    "Field4" : [ { "id": "123"} ]
} ,
{
    "Field3" : "ABC2",
    "Field4" : [ { "id": "123"} ]
}
1. Java way  
    A. use Mongo find method to get the ABC document from Mongo DB
    B. for Loop to Iterate the Field2 Json Array
    C. Again for Loop to Iterate over Field4 Json Array
    D. Inside the nested for loop I've if condition to Match id value to "123"
    E. Store the Matching subdocument into List 

2. Mongo Way
   A. Use Aggregation query to get the desired output from DB.No Loops and conditions in the Java side. 
   B. Aggregation Query below stages
    I)  $Match - match the ABC document
    II) $unwind - Field2
    III) $unwind - Field4
    IV) $match - Match the with id ( value is "123")
    V) $group - group the document  based on Field3 (based on "ABC1" or "ABC2") 
    VI) execute aggregation and return results

两者都运行良好并返回正确的结果。
问题是哪个更好,为什么?我在restful服务get方法中使用了聚合,那么并行执行聚合查询1000次或更多次会导致性能问题吗?

第二种方法可能更好,因为它 returns 来自数据存储的结果较小;通过电线传输钻头很昂贵。

使用聚合,整个查询在 MongoDB 服务器上作为单个进程执行 - 应用程序将从服务器获取结果游标。

使用 Java 程序,您还可以从数据库服务器获取游标作为应用程序处理的输入。来自服务器的响应游标将是更大的数据集,并将使用更多的网络带宽。然后在应用程序中进行处理,这就增加了更多的步骤来完成查询。

我认为聚合选项是更好的选择 - 因为所有处理(初始匹配和过滤数组)作为单个进程在数据库服务器上发生。

另外,请注意您发布的聚合查询步骤可以高效完成。您可以在 两个阶段 中执行这些操作,而不是多个阶段(2、3、4 和 5) - 在外部数组上使用 $project$map然后在内部数组 $filter 然后在外部数组 $filter 上。

聚合:

db.test.aggregate( [
  { 
      $addFields: { 
          Field2: { 
              $map: {
                   input: "$Field2",
                      as: "fld2",
                      in: {
                           Field3: "$$fld2.Field3",
                           Field4: { 
                               $filter: {
                                   input: "$$fld2.Field4",
                                      as: "fld4",
                                    cond: {  $eq: [ "$$fld4.id", "123" ] }
                               }
                           }
                       }
                 } 
          }
      }
  },
  { 
      $addFields: { 
          Field2: { 
              $filter: {
                   input: "$Field2",
                      as: "f2",
                    cond: {  $gt: [ { $size: "$$f2.Field4" }, 0 ] }
              }
          }
      }
  },
] )