Member count incorrect for Virtual Chassis members in search results #3900

Closed
opened 2025-12-29 18:31:52 +01:00 by adam · 2 comments
Owner

Originally created by @steffann on GitHub (Jul 27, 2020).

Originally assigned to: @jeremystretch on GitHub.

Environment

  • Python version: 3.6.9
  • NetBox version: 2.9-beta1

Steps to Reproduce

  1. Create a Virtual Chassis with multiple members
  2. Search for the name of the virtual chassis
  3. Inspect the number of reported members

For example: create virtual chassis cr1.ams2 with members cr1.ams2 (master), fusion1.ams1, fusion1.ams2 and fusion2.ams3:
image

Searching for cr1.ams2 shows:
image

Expected Behavior

I expected to see Members = 4.

Observed Behavior

It shows Members = 16.

Originally created by @steffann on GitHub (Jul 27, 2020). Originally assigned to: @jeremystretch on GitHub. ### Environment * Python version: 3.6.9 * NetBox version: 2.9-beta1 ### Steps to Reproduce 1. Create a Virtual Chassis with multiple members 2. Search for the name of the virtual chassis 3. Inspect the number of reported members For example: create virtual chassis `cr1.ams2` with members `cr1.ams2` (master), `fusion1.ams1`, `fusion1.ams2` and `fusion2.ams3`: ![image](https://user-images.githubusercontent.com/509689/88511969-103bbe80-cfe6-11ea-8971-113ba502d75a.png) Searching for `cr1.ams2` shows: ![image](https://user-images.githubusercontent.com/509689/88512049-2d708d00-cfe6-11ea-917b-9c6598dba3a5.png) ### Expected Behavior I expected to see Members = 4. ### Observed Behavior It shows Members = 16.
adam added the type: bugstatus: acceptedbeta labels 2025-12-29 18:31:52 +01:00
adam closed this issue 2025-12-29 18:31:52 +01:00
Author
Owner

@steffann commented on GitHub (Jul 27, 2020):

I discovered that this can be fixed by explicitly telling Django to count distinct devices with member_count=Count('members', distinct=True) in SEARCH_TYPES. I will provide a PR.

@steffann commented on GitHub (Jul 27, 2020): I discovered that this can be fixed by explicitly telling Django to count distinct devices with `member_count=Count('members', distinct=True)` in `SEARCH_TYPES`. I will provide a PR.
Author
Owner

@jeremystretch commented on GitHub (Jul 27, 2020):

It looks like this is triggered specifically when searching for virtual chassis. The q filter matches against both the virtual chassis name (in v2.9) and the name of the associated master device (if any). This results in joining the dcim_device table twice:

SELECT "dcim_virtualchassis"."id",
       "dcim_virtualchassis"."created",
       "dcim_virtualchassis"."last_updated",
       "dcim_virtualchassis"."master_id",
       "dcim_virtualchassis"."name",
       "dcim_virtualchassis"."domain",
       COUNT("dcim_device"."id") AS "member_count"
  FROM "dcim_virtualchassis"
  LEFT OUTER JOIN "dcim_device"
    ON ("dcim_virtualchassis"."id" = "dcim_device"."virtual_chassis_id")
  LEFT OUTER JOIN "dcim_device" T3
    ON ("dcim_virtualchassis"."id" = T3."virtual_chassis_id")
 WHERE (UPPER("dcim_virtualchassis"."name"::text) LIKE UPPER('%MyVC1%') OR UPPER(T3."name"::text) LIKE UPPER('%MyVC1%') OR UPPER("dcim_virtualchassis"."domain"::text) LIKE UPPER('%MyVC1%'))
 GROUP BY "dcim_virtualchassis"."id"
 ORDER BY "dcim_virtualchassis"."name" ASC
 LIMIT 1

This problem affects not only the global search, but everywhere VirtualChassisFilterSet is used (i.e. the virtual chassis list and REST API endpoint). So, the fix will entail a greater scope than just the global search view.

Per my comment on #3672, we need to be really careful about invoking DISTINCT() in queries. When attaching multiple related object counts, it can lead to severe performance degradation. (It would be preferable to use subqueries in these instances, but #3672 discusses the current problem with that approach.)

For this specific issue, I think it probably makes sense to use DISTINCT(), however we want to ensure that a) doing so won't impose performance penalties at scale, and b) it gets implemented consistently across all affected QuerySets.

@jeremystretch commented on GitHub (Jul 27, 2020): It looks like this is triggered specifically when _searching_ for virtual chassis. The `q` filter matches against both the virtual chassis name (in v2.9) and the name of the associated master device (if any). This results in joining the `dcim_device` table twice: ```sql SELECT "dcim_virtualchassis"."id", "dcim_virtualchassis"."created", "dcim_virtualchassis"."last_updated", "dcim_virtualchassis"."master_id", "dcim_virtualchassis"."name", "dcim_virtualchassis"."domain", COUNT("dcim_device"."id") AS "member_count" FROM "dcim_virtualchassis" LEFT OUTER JOIN "dcim_device" ON ("dcim_virtualchassis"."id" = "dcim_device"."virtual_chassis_id") LEFT OUTER JOIN "dcim_device" T3 ON ("dcim_virtualchassis"."id" = T3."virtual_chassis_id") WHERE (UPPER("dcim_virtualchassis"."name"::text) LIKE UPPER('%MyVC1%') OR UPPER(T3."name"::text) LIKE UPPER('%MyVC1%') OR UPPER("dcim_virtualchassis"."domain"::text) LIKE UPPER('%MyVC1%')) GROUP BY "dcim_virtualchassis"."id" ORDER BY "dcim_virtualchassis"."name" ASC LIMIT 1 ``` This problem affects not only the global search, but everywhere VirtualChassisFilterSet is used (i.e. the virtual chassis list and REST API endpoint). So, the fix will entail a greater scope than just the global search view. Per [my comment](https://github.com/netbox-community/netbox/issues/3672#issuecomment-661905757) on #3672, we need to be really careful about invoking `DISTINCT()` in queries. When attaching multiple related object counts, it can lead to severe performance degradation. (It would be preferable to use subqueries in these instances, but #3672 discusses the current problem with that approach.) For _this specific_ issue, I think it probably makes sense to use `DISTINCT()`, however we want to ensure that a) doing so won't impose performance penalties at scale, and b) it gets implemented consistently across all affected QuerySets.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#3900