使用 mongoose 获取子文档的节点 api

Posted

技术标签:

【中文标题】使用 mongoose 获取子文档的节点 api【英文标题】:node api to fetch subdocuments using mongoose 【发布时间】:2020-05-19 04:00:29 【问题描述】:

我的 MongoDB 存储具有以下结构的文档:


    "application_detail":,
    "curl_detail":
        "Curl1":
            "key1":"value1",
            "key2":"value2"
        ,
        "Curl2":
            "key1":"value1",
            "key2":"value2"        
        ,
        "Curl3":
            "key1":"value1",
            "key2":"value2"
        ,
        "Curl4":
            "key1":"value1",
            "key2":"value2"
        ,
        /*total number of curls are unknown*/
    

如何使用 express 和 mongoose 从 mongoDB 获取 key1 下存在的所有卷曲 curl_detail

预期输出:


    "curl_detail": 
        "Curl1": 
            "key1": "value1"
        ,
        "Curl2": 
            "key1": "value1"
        ,
        "Curl3": 
            "key1": "value1"
        ,
        "Curl4": 
            "key1": "value1"
        
    

注意:卷发总数未知。

【问题讨论】:

查询的预期输出是什么样的?从 mongoose 查询中发布您想要的预期输出。 "curl_detail": "Curl1": "key1":"value1" , "Curl2": "key1":"value1" , "Curl3": "key1":"value1" , "Curl4": "key1":"value1" /* so on for all the curls present in that document */ @AnkitaKuchhadiya 这是我期望的输出。 这个结果对你也有用吗? "curl_detail": "Curl1": "value1", "Curl2": "value1", "Curl3": "value1", "Curl4": "value1" @SuleymanSah 这对我有用。您能否提供一个等效的猫鼬代码? 请查看我更新的答案以使用 mongoose 聚合。 【参考方案1】:

如果此结果也适合您:

[
  
    "curl_detail": 
      "Curl1": "value1",
      "Curl2": "value1",
      "Curl3": "value1",
      "Curl4": "value1"
    
  
]

您可以通过$objectToArray 和$arrayToObject 使用以下聚合

db.collection.aggregate([
  
    $addFields: 
      curl_detail: 
        $map: 
          "input": 
            "$objectToArray": "$curl_detail"
          ,
          "as": "el",
          "in": 
            "k": "$$el.k",
            "v": "$$el.v.key1",

          
        
      
    
  ,
  
    $project: 
      _id: 0,
      curl_detail: 
        $arrayToObject: "$curl_detail"
      
    
  
])

Playground

您可以像这样将这个聚合与猫鼬一起使用,假设您的模型是 MyModel:

MyModel.aggregate([
  
    $addFields: 
      curl_detail: 
        $map: 
          input: 
            $objectToArray: '$curl_detail'
          ,
          as: 'el',
          in: 
            k: '$$el.k',
            v: '$$el.v.key1'
          
        
      
    
  ,
  
    $project: 
      _id: 0,
      curl_detail: 
        $arrayToObject: '$curl_detail'
      
    
  
]).then(res => 
  console.log(res);
);

【讨论】:

感谢您的回复。 @Hlib 为我提供了我正在寻找的完美结果。 "curl_detail": "Curl1": "value1", "Curl2": "value1", "Curl3": "value1", "Curl4": "value1" 这个输出对我来说是一种解决方法。 @KapilKhandelwal 他刚刚在我的回答之后更新了他的答案,复制并编辑了一行,这并不友好。如果你比较他的编辑历史,你会看到这一点。 @KapilKhandelwal 你至少可以支持我的答案,但如果你也可以将其标记为答案,我将不胜感激。【参考方案2】:

我想建议您从

更改数据结构
"curl_detail": 
    "Curl1": 
        "key1": "value1",
        "key2": "value2"
    ,
    "Curl2": 
        "key1": "value1",
        "key2": "value2"
    

"curl_detail": [
        "key1": "value1",
        "key2": "value2"
    ,
    
        "key1": "value1",
        "key2": "value2"
    
]

将数据结构存储在数组中可以让您以更简单的方式找到一些数据。也没有必要拥有具有Curl1Curl2 等属性的对象。

对于新的数据结构,已经有了一些答案和解释:

1) Mongo find value with unknown parent key

2) Query MongoDB by value when parent key is unknown

3)MongoDB: Find document given field values in an object with an unknown key

更新

如果无法更改数据结构,请查看此解决方案(使用$arrayToObject / $objectToArray 确定嵌套键的名称,例如“Curl1”):

db.collection.aggregate([
        $addFields: 
            curl_detail: 
                $arrayToObject: 
                    $map: 
                        input: 
                            $objectToArray: "$curl_detail"
                        ,
                        as: "details",
                        in: 
                            k: "$$details.k",
                            v: 
                                key1: "$$details.v.key1"
                            
                        
                    
                
            
        
    ,
    
        $project: 
            _id: 0,
            curl_detail: 1
        
    
])

这会输出以下内容:

[
  
    "curl_detail": 
      "Curl1": 
        "key1": "value1"
      ,
      "Curl2": 
        "key1": "value1"
      ,
      "Curl3": 
        "key1": "value1"
      ,
      "Curl4": 
        "key1": "value1"
      
    
  
]

您可以通过Mongo Playground查看

【讨论】:

感谢 Hlib 的推荐。但这暂时超出了我的范围。我不允许对数据进行任何更改。我只需要在 UI 上获取并填充它。 @KapilKhandelwal 更新的答案只是我的答案的修订。这不友好。请查看他的编辑。 @SuleymanSah 实际上我也使用了相同的运算符,因为这个问题没有其他解决方案。最后,我的解决方案返回了正确的数据结构。请保持礼貌,接受他人的意见。【参考方案3】:

您可以对要查找的查询使用投影:

collection.find(, "curl_detail":1, (findError, results) => 
  if(findError)  
    //handle the error
    return;
  
  // here is the expected result
  console.log();
);

【讨论】:

这给了我这个结果: "curl_detail" : "Curl1" : "key1" : "value1", "key2" : "value2" , "Curl2" : "key1" : "value1", "key2" : "value2" , "Curl3" : "key1" : "value1", "key2" : "value2" , "Curl4" : "key1" : "value1", "key2" : "value2" 它是如何工作的? @SuleymanSah 你是对的。这将返回该 Curl 的所有字段,这不是我所期望的。所有卷发我只需要key1。 @Shubh @Ankita 如果我错了,请纠正我。

以上是关于使用 mongoose 获取子文档的节点 api的主要内容,如果未能解决你的问题,请参考以下文章

访问 mongoose 父文档以获取子文档中的默认值

MongoDB/Mongoose 一对多,在子节点中引用父节点 - 分组并加入

如何查询和排序 Mongoose 子文档

子文档中行的 Mongoose 聚合“$sum”

创建后如何在 mongoose 中填充子文档?

使用 mongoose 添加子子文档项