【问题标题】:Querying nested object arrays查询嵌套对象数组
【发布时间】:2020-03-19 08:38:25
【问题描述】:

我有一个类别架构和一个示例数据,如下所示:

{
    categories: [], -- array of category object
    id: String,
    name: String
}

{ 
 "id" : 1,
 "name" : "cat1",
 "categories" : [ 
    {
    "id:2,
    "name": "cat2",
    "categories" : [
        {
        "id":3,
        "name": "cat3,
        }]
    }]
}



我想按名称获取类别,但如果说类似的话,我只能达到第一级

categories.findOne({"name": "cat1"}) -- returns cat1 correctly
categories.findOne({"name": "cat2"}) -- returns nothing

如何在子类别中搜索?

【问题讨论】:

  • 您确定这是数据的确切格式吗? categories 内是否有嵌套的 categories?
  • categories.findOne({"categories.name": "cat2"}) 可以完成这项工作,但它有点硬编码,如果第一级有cat2(id 的级别:1),它将不会返回
  • 是的,这正是我的问题:)
  • 您想只查找类别或类别及其子类别吗?

标签: mongodb mongoose


【解决方案1】:

您可以使用mongoose-mpath 包创建树层次结构。

步骤如下:

1-) 使用此插件创建类别架构。

const mongoose = require("mongoose");
const MpathPlugin = require("mongoose-mpath");

const schema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  }
});

schema.plugin(MpathPlugin);

const Category = mongoose.model("Category", schema);

module.exports = { Category };

2-) 发布路径以插入具有层次结构的类别:

const express = require("express");
const router = express.Router();
const { Category } = require("../models/category");

router.post("/", async (req, res) => {
  const { name, parent } = req.body;

  const category = await Category.create({ name, parent });

  res.status(201).send(category);
});

使用这条路线,用邮递员创建类别:

Root Category:(有ROOT类就好,root没有父类)

{
    "name": "ROOT"
}

响应将是这样的:(如您所见,此插件在内部添加了一个路径字段以维护层次结构)

{
    "_id": "5dd95adf997fc53e1ce944a7",
    "name": "ROOT",
    "path": "5dd95adf997fc53e1ce944a7",
    "__v": 0
}

Cat1 类别:(请注意,我们将父字段设置为根类别 id,即 5dd95adf997fc53e1ce944a7)

{
    "name": "Cat1",
    "parent": "5dd95adf997fc53e1ce944a7"
}

Cat1 的结果:

{
    "_id": "5dd95b21997fc53e1ce944a8",
    "name": "Cat1",
    "parent": "5dd95adf997fc53e1ce944a7",
    "path": "5dd95adf997fc53e1ce944a7#5dd95b21997fc53e1ce944a8",
    "__v": 0
}

Cat11 类别:(请注意,我们将父字段设置为 Cat1 id,即 5dd95adf997fc53e1ce944a7)

{
    "name": "Cat11",
    "parent": "5dd95adf997fc53e1ce944a7"
}

Cat11 的结果:

{
    "_id": "5dd95b8e997fc53e1ce944aa",
    "name": "Cat11",
    "parent": "5dd95adf997fc53e1ce944a7",
    "path": "5dd95adf997fc53e1ce944a7#5dd95b8e997fc53e1ce944aa",
    "__v": 0
}

要按名称查找类别,您可以使用以下 get 路线: (为简单起见,我对类别名称进行了硬编码,您可以从 req.body 或 req.query 中获取类别名称)

router.get("/", async (req, res) => {
  let category = await Category.findOne({
    name: "Cat11" 
  });

  res.status(200).send(category);
});

这将返回 Cat11 类别文档,如下所示:

{
    "_id": "5dd95b8e997fc53e1ce944aa",
    "name": "Cat11",
    "parent": "5dd95adf997fc53e1ce944a7",
    "path": "5dd95adf997fc53e1ce944a7#5dd95b8e997fc53e1ce944aa",
    "__v": 0
}

如果你想获取找到的类别的子类别,你可以尝试mongoose-mpathgetChildrenTree之类的方法。

【讨论】:

    【解决方案2】:

    您正在尝试使用 findOne 方法查询特定字段,但查询方法在集合级别工作。为了查询集合内文档中的嵌套字段,请使用点表示法。

    Documentation

    命令(在 MongoDB shell 中)将类似于...

    db.findOne({"categories.name": "cat2"})
    

    【讨论】:

    • 谢谢,但我不知道“cat2”在哪个级别。所以它可能是“categories.categories.name”等等。这就是为什么我不能使用点表示法。
    猜你喜欢
    • 1970-01-01
    • 2012-07-23
    • 2016-09-05
    • 2021-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多