Mongoose 中的 populate 不怎么好用?试试 Virtual populate

阅读时长 8 分钟读完

前言

在使用 Mongoose 进行数据建模时,我们经常会遇到需要关联查询的场景。Mongoose 中提供了 populate 方法来实现关联查询,但是在实际使用中,我们可能会遇到一些问题。

在本文中,我们将介绍 Mongoose 中的 populate 方法存在的问题,并介绍一种更好的解决方案:Virtual populate。同时,本文还将通过示例代码来帮助读者更好地理解和应用。

Mongoose 中的 populate 方法存在的问题

性能问题

当我们使用 populate 方法进行关联查询时,Mongoose 会向数据库发送多条查询语句,这会导致查询性能的下降。例如,我们有一个模型 A,其中包含一个关联模型 B 的引用,我们想要查询 A 中的所有记录以及关联的 B 记录,代码如下:

-- -------------------- ---- -------
----- -------- - --------------------

----- ------- - --- -----------------
  ----- -------
---

----- ------- - --- -----------------
  -- -
    ----- -------------------------------
    ---- ----
  --
---

----- - - ------------------- ---------
----- - - ------------------- ---------

--------------------------------- ----- -- -
  -- ------
---

上述代码中,当我们执行 A.find().populate('b').exec() 时,Mongoose 会向数据库发送两条查询语句,一条是查询 A 的所有记录,另一条是查询 B 中与 A 相关的记录。当数据量较大时,这会导致查询性能的下降。

查询结果不能自定义

当我们使用 populate 方法进行关联查询时,我们不能自定义查询结果。例如,我们有一个模型 A,其中包含一个关联模型 B 的引用,我们想要查询 A 中的所有记录以及关联的 B 记录中的 name 字段,代码如下:

-- -------------------- ---- -------
----- -------- - --------------------

----- ------- - --- -----------------
  ----- -------
---

----- ------- - --- -----------------
  -- -
    ----- -------------------------------
    ---- ----
  --
---

----- - - ------------------- ---------
----- - - ------------------- ---------

---------------------- ------------------ ----- -- -
  -- ------
---

上述代码中,当我们执行 A.find().populate('b', 'name').exec() 时,我们只能查询关联模型 B 中的 name 字段,不能查询其他字段。

Virtual populate 的优势

为了解决 Mongoose 中 populate 方法存在的问题,我们可以使用 Virtual populate。Virtual populate 是一种通过虚拟字段来实现关联查询的方法,它具有以下优势:

性能优化

使用 Virtual populate 可以避免 populate 方法存在的性能问题。例如,我们有一个模型 A,其中包含一个关联模型 B 的引用,我们想要查询 A 中的所有记录以及关联的 B 记录,代码如下:

-- -------------------- ---- -------
----- -------- - --------------------

----- ------- - --- -----------------
  ----- -------
---

----- ------- - --- -----------------
  -- -
    ----- -------------------------------
    ---- ----
  --
---

----------------------- -
  ---- ----
  ----------- ----
  ------------- ------
  -------- -----
---

----- - - ------------------- ---------
----- - - ------------------- ---------

------------------------------------ ----- -- -
  -- ------
---

上述代码中,我们通过 virtual 方法定义了一个虚拟字段 bObj,它与模型 B 相关联。当我们执行 A.find().populate('bObj').exec() 时,Mongoose 只会向数据库发送一条查询语句,这可以优化查询性能。

查询结果可以自定义

使用 Virtual populate 可以自定义查询结果。例如,我们有一个模型 A,其中包含一个关联模型 B 的引用,我们想要查询 A 中的所有记录以及关联的 B 记录中的 name 字段,代码如下:

-- -------------------- ---- -------
----- -------- - --------------------

----- ------- - --- -----------------
  ----- -------
---

----- ------- - --- -----------------
  -- -
    ----- -------------------------------
    ---- ----
  --
---

----------------------- -
  ---- ----
  ----------- ----
  ------------- ------
  -------- -----
  -------- -
    ------- -------
  --
---

----- - - ------------------- ---------
----- - - ------------------- ---------

------------------------------------ ----- -- -
  -- ------
---

上述代码中,我们通过 virtual 方法定义了一个虚拟字段 bObj,它与模型 B 相关联,并且指定了查询结果中只包含 name 字段。

示例代码

下面是一个示例代码,它演示了如何使用 Virtual populate 进行关联查询:

-- -------------------- ---- -------
----- -------- - --------------------

----- ------- - --- -----------------
  ----- -------
---

----- ------- - --- -----------------
  --- -
    -
      ----- -------------------------------
      ---- ----
    --
  --
---

------------------------ -
  ---- ----
  ----------- -----
  ------------- ------
---

----- - - ------------------- ---------
----- - - ------------------- ---------

------ -- -- -
  ----- -------------------------------------------- -
    ---------------- -----
    ------------------- -----
  ---

  ----- ----------
    - ----- ---- --
    - ----- ---- --
    - ----- ---- --
  ---

  ----- - - ----- ----------
    --- -
      --------------------------
      --------------------------
      --------------------------
    --
  ---

  ----------------- -------------------------------------
-----

上述代码中,我们定义了两个模型 A 和 B,模型 A 中包含一个关联模型 B 的数组引用。我们通过 virtual 方法定义了一个虚拟字段 bsObj,它与模型 B 相关联。当我们执行 A.findById(a._id).populate('bsObj') 时,Mongoose 会向数据库发送一条查询语句,查询模型 A 中的记录以及关联的 B 记录。

总结

本文介绍了 Mongoose 中的 populate 方法存在的问题,并介绍了一种更好的解决方案:Virtual populate。Virtual populate 可以避免 populate 方法存在的性能问题,并且可以自定义查询结果。我们还通过示例代码演示了如何使用 Virtual populate 进行关联查询。希望读者可以通过本文更好地理解和应用 Virtual populate。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/651039b895b1f8cacd8d197d

纠错
反馈