猫鼬查询从多集合中获取数据

时间:2019-11-01 12:56:47

标签: node.js mongodb express mongoose

当我结合2个表从mongoDB集合中获取数据时,出乎我的意料。请任何人帮我解决同样的问题。

收藏集:

食谱

{
    "_id":{"$oid":"5dada3c5761bb32a1201d4da"},
    "CategoryName":"Biryani"
}
{
    "_id":{"$oid":"5dada3c5761bb32a1201d4db"},
    "CategoryName":"Mutton Biryani"
}
{
    "_id":{"$oid":"5dada3c5761bb32a1201d4d4"},
    "CategoryName":"Chicken Biryani"
}
{
    "_id":{"$oid":"5daea43a517cf601a7e80a3b"},
    "CategoryName":"Kathirikai gothsu"
}

食谱:

{
    "_id":{"$oid":"5daffda85d9b4fd19ae4da30"},
    "recipeTitle":"Mutton dum biryani",
    "Recipetags":["Indian","NonVeg","Lunch"],
    "cookTime":"30 Mins",
    "recipeCategoryId":[{"$oid":"5dada3c5761bb32a1201d4da"},{"$oid":"5dada3c5761bb32a1201d4db"},{"$oid":"5dada3c5761bb32a1201d4dc"}],
    "recipeCuisienId":"Indian",
    "recepeType":false,
    "availaleStreaming":"TEXT",
    "postedOn":{"$date":{"$numberLong":"0"}},
    "postedBy":"shiva@yopmail.com"
}
{
    "_id":{"$oid":"5daffda85d9b4fd19ae4da30"},
    "recipeTitle":"Mutton Chicken biryani",
    "Recipetags":["Indian","NonVeg","Lunch"],
    "cookTime":"30 Mins",
    "recipeCategoryId":[{"$oid":"5dada3c5761bb32a1201d4da"},{"$oid":"5dada3c5761bb32a1201d4d4"},{"$oid":"5dada3c5761bb32a1201d4dc"}],
    "recipeCuisienId":"Indian",
    "recepeType":false,
    "availaleStreaming":"TEXT",
    "postedOn":{"$date":{"$numberLong":"0"}},
    "postedBy":"shiva@yopmail.com"
}

用户:

{
    "_id":{"$oid":"5da428b85e3cbd0f153c7f3b"},
    "emailId":"shiva@yopmail.com",
    "fullName":"siva prakash",
    "accessToken":"xxxxxxxxxxxxx",
    "__v":{"$numberInt":"0"}
}

节点js中的当前猫鼬代码

RecipeCatagory.aggregate([
        { "$match": { "_id": mongoose.Types.ObjectId(id) } },
        {
            "$lookup": {
                "from": "recipes",
                "localField": "_id",
                "foreignField": "recipeCategoryId",
                "as": "recipes"
            }
        },
        { "$unwind": "$recipes" },
        { "$unwind": "$recipes.recipeCategoryId" },
        {
            "$match": {
                "recipes.recipeCategoryId": mongoose.Types.ObjectId(id)
            }
        },
        {
            "$lookup": {
                "from": "users",
                "localField": "emailId",
                "foreignField": "recipes.postedBy",
                "as": "users"
            }
        },

    ])
        .exec(function (err, recipes) {
            if (err) {
                response
                    .status(400)
                    .json({
                        "status": "Failed",
                        "message": "Error",
                        "data": err | err.message
                    });
                return
            } else {
                response
                    .status(200)
                    .json({
                        "status": "Ok",
                        "message": "Success",
                        "data": recipes
                    });
                return
            }
        })

使用上述查询的当前输出

{
    "status": "Ok",
    "message": "Success",
    "data": [
        {
            "_id": "5dada3c5761bb32a1201d4da",
            "CategoryName": "Biryani",
            "recipes": {
                "_id": "5daffda85d9b4fd19ae4da30",
                "recipeTitle": "Mutton dum biryani",
                "Recipetags": [
                    "Indian",
                    "NonVeg",
                    "Lunch"
                ],
                "cookTime": "30 Mins",
                "recipeCategoryId": "5dada3c5761bb32a1201d4da",
                "recipeCuisienId": "Indian",
                "recepeType": false,
                "availaleStreaming": "TEXT",
                "postedOn": "1970-01-01T00:00:00.000Z",
                "postedBy": "shiva@yopmail.com"
            },
            "users": [
                {
                    "_id": "5da428b85e3cbd0f153c7f3b",
                    "emailId": "shiva@yopmail.com",
                    "fullName": "siva prakash",
                    "accessToken": "42eb19a0-ee57-11e9-86f7-a7b758fb7271",
                    "__v": 0
                }
            ]
        },
        {
            "_id": "5dada3c5761bb32a1201d4da",
            "CategoryName": "Biryani",
            "recipes": {
                "_id": "5daffda85d9b4fd19ae4da31",
                "recipeTitle": "Kumbakonam kathirikai gothsu",
                "Recipetags": [
                    "Indian",
                    "Veg"
                ],
                "cookTime": "30 Mins",
                "recipeCategoryId": "5dada3c5761bb32a1201d4da",
                "recipeCuisienId": "Indian",
                "recepeType": true,
                "availaleStreaming": "TEXT",
                "postedOn": "1970-01-01T00:00:00.000Z",
                "postedBy": "shiva@yopmail.com"
            },
            "users": [
                {
                    "_id": "5da428b85e3cbd0f153c7f3b",
                    "emailId": "shiva@yopmail.com",
                    "fullName": "siva prakash",
                    "accessToken": "xxxxxxxxxxxxx",
                    "__v": 0
                }
            ]
        }
    ]
}


**Expected Out:**
    {
    "status": "Ok",
    "message": "Success",
    "data": [
        {
            "_id": "5dada3c5761bb32a1201d4da",
            "CategoryName": "chiken Biryani",
            "recipes": {
                "_id": "5daffda85d9b4fd19ae4da30",
                "recipeTitle": "Mutton dum biryani",
                "Recipetags": [
                    "Indian",
                    "NonVeg",
                    "Lunch"
                ],
                "cookTime": "30 Mins",
                "recipeCategoryId": "5dada3c5761bb32a1201d4da",
                "recipeCuisienId": "Indian",
                "recepeType": false,
                "availaleStreaming": "TEXT",
                "postedOn": "1970-01-01T00:00:00.000Z",
                "postedBy": "shiva@yopmail.com"
            },
            "users": [
                {
                    "_id": "5da428b85e3cbd0f153c7f3b",
                    "emailId": "shiva@yopmail.com",
                    "fullName": "siva prakash",
                    "accessToken": "42eb19a0-ee57-11e9-86f7-a7b758fb7271",
                    "__v": 0
                }
            ]
        },
        {
            "_id": "5dada3c5761bb32a1201d4da",
            "CategoryName": "Biryani",
            "recipes": [
                {
                "_id": "5daffda85d9b4fd19ae4da31",
                "recipeTitle": "Mutton dum biryani",
                "Recipetags": [
                    "Indian",
                    "Veg"
                ],
                "cookTime": "30 Mins",
                "recipeCategoryId": "5dada3c5761bb32a1201d4da",
                "recipeCuisienId": "Indian",
                "recepeType": true,
                "availaleStreaming": "TEXT",
                "postedOn": "1970-01-01T00:00:00.000Z",
                "postedBy": "shiva@yopmail.com"
                },
                {
                "_id": "5daffda85d9b4fd19ae4da31",
                "recipeTitle": "Chicken biryani",
                "Recipetags": [
                    "Indian",
                    "Veg"
                ],
                "cookTime": "30 Mins",
                "recipeCategoryId": "5dada3c5761bb32a1201d4da",
                "recipeCuisienId": "Indian",
                "recepeType": true,
                "availaleStreaming": "TEXT",
                "postedOn": "1970-01-01T00:00:00.000Z",
                "postedBy": "shiva@yopmail.com"
                }
            ],
            "users": [
                {
                    "_id": "5da428b85e3cbd0f153c7f3b",
                    "emailId": "shiva@yopmail.com",
                    "fullName": "siva prakash",
                    "accessToken": "xxxxxxxxxxxx",
                    "__v": 0
                }
            ]
        }
    ]
}

我很想得到期望的结果...我希望将食谱作为具有食谱类别的数组包含在食谱集合中...

1 个答案:

答案 0 :(得分:2)

基本上,您这样做的方式是错误的,应该从Recipe模型进行查询。您已经具有“类别ID值” ,它们包含在该文档的数组中。

基本上,您应该具有以下内容:

const wantedCategories = [
  ObjectId("5dada3c5761bb32a1201d4da"),
  ObjectId("5dada3c5761bb32a1201d4db")
];

let data = await Recipe.aggregate([
  // Match wanted category(ies)
  { "$match": {
    "recipeCategoryId": { "$in": wantedCategories }
  }},
  // Filter the content of the array
  { "$addFields": {
    "recipeCategoryId": {
      "$filter": {
        "input": "$recipeCategoryId",
        "cond": {
          "$in": [ "$$this", wantedCategories ]
        }
      }
    }
  }},
  // Lookup the related matching category(ies)
  { "$lookup": {
    "from": RecipeCategory.collection.name,
    "let": { "recipeCategoryIds": "$recipeCategoryId" },
    "pipeline": [
      { "$match": {
        "$expr": { "$in": [ "$_id", "$$recipeCategoryIds" ] }
      }}
    ],
    "as": "recipeCategoryId"
  }},
  // Lookup the related user to postedBy
  { "$lookup": {
    "from": User.collection.name,
    "let": { "postedBy": "$postedBy" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": [ "$emailId", "$$postedBy" ] } } }
    ],
    "as": "postedBy"
  }},
  // postedBy is "singular"
  { "$unwind": "$postedBy" }
]);

哪个会返回如下结果:

{
  "data": [
    {
      "_id": "5dbce992010163139853168c",
      "Recipetags": [
        "Indian",
        "NonVeg",
        "Lunch"
      ],
      "recipeCategoryId": [
        {
          "_id": "5dada3c5761bb32a1201d4da",
          "CategoryName": "Biryani",
          "__v": 0
        },
        {
          "_id": "5dada3c5761bb32a1201d4db",
          "CategoryName": "Mutton Biryani",
          "__v": 0
        }
      ],
      "recipeTitle": "Mutton dum biryani",
      "cookTime": "30 Mins",
      "recepeType": false,
      "postedBy": {
        "_id": "5dbce992010163139853168e",
        "emailId": "shiva@yopmail.com",
        "fullName": "siva prakash",
        "accessToken": "xxxxxxxxxxxxx",
        "__v": 0
      },
      "__v": 0
    },
    {
      "_id": "5dbce992010163139853168d",
      "Recipetags": [
        "Indian",
        "NonVeg",
        "Lunch"
      ],
      "recipeCategoryId": [
        {
          "_id": "5dada3c5761bb32a1201d4da",
          "CategoryName": "Biryani",
          "__v": 0
        }
      ],
      "recipeTitle": "Mutton Chicken biryani",
      "cookTime": "30 Mins",
      "recepeType": false,
      "postedBy": {
        "_id": "5dbce992010163139853168e",
        "emailId": "shiva@yopmail.com",
        "fullName": "siva prakash",
        "accessToken": "xxxxxxxxxxxxx",
        "__v": 0
      },
      "__v": 0
    }
  ]
}
  

注意:实际上,我确实使用RecipeCategory而不是问题中显示的RecipeCatagory来纠正模型的英文拼写。根据需要应用到自己的实现中。

您可能会注意到在不同阶段的查询表单和聚合运算符表单中,$in与“ ID列表”的使用。就我个人而言,即使当前仅提供一个值,我也将以这种方式进行编码,因为这意味着在事件I中,除了 input 变量外,几乎没有其他更改想要多个值,例如,多面搜索选项中的“多个类别”。

尽管这仍然适用于问题中的奇异值,但这证明了“列表”自变量方法。

整个过程都遵循注释在每个管道阶段所说的,即您首先通过选定的“ category” 值将 recipes 集合中的所需“文档”进行匹配(s)。然后,我们只想删除这些文档数组中类别的所有不匹配数据。如果您只想显示与该食谱相关的所有类别(无论它们是否符合条件),则实际上可以将其视为“可选”。在这种情况下,您需要做的就是删除包含$filter语句的阶段,这样代码就会很愉快地工作。

然后当然有$lookup阶段,每个与相关的集合都是一个阶段。这里的示例实际上显示了$lookup流水线阶段的表达形式。再次,这实际上仅是为了演示,因为标准localFieldforeignField格式对于您在此处要执行的操作来说是完美的,并且不需要其他语法。无论如何,MongoDB基本上都会将较旧的语法转换为较新的表达形式,如内部所示。

您可能会注意到Model.collection.name参数中from的用法。当用猫鼬编码时,这实际上是一件方便的事。 MongoDB本身希望实际的集合名称作为此处的参数。由于 mongoose 通常会为所引用的实际集合提供多种名称,或者对模型定义采用显式参数,因此使用模型中的.collection.name访问器可确保您拥有正确的名称。实际的集合名称,即使此名称在模型定义中的某些时间发生了变化。

这里唯一的其他简单步骤是最后的$unwind,并且仅因为$lookup的输出是始终一个数组,并且在这里替换了{匹配的内容相关的{1}}属性总是 个项目。因此,为了简化结果的可读性,我们可以将其设为单个值,而不是在此处使用数组。


对于所有内容如何组合的更多上下文,这是语句的代码和数据的创建全部包含在一个独立的列表中,当然实际上是从上面获得的“输出”获得了: / p>

postedBy