Group Search sort based on algorithmic score
The Group Search dropdown currently sorts by namespace.name, then namespace.id. A new sort should be added within the search method inside app/models/namespace.rb. That sort should use an algorithm to make sure that:
- Exact search matches show first
- Top level groups weighted higher than sub groups based on search term
Some areas to look for inspiration:
- The user search has an example that could be a useful starting point: app/models/user.rb
- The project model contains a sorted_by_similarity_descscope which could be a cool way to do this: app/models/project.rb
current SQL
/*application:web,correlation_id:01F7KW07CJ0W82358TE9HRPGJS,endpoint_id:GET /api/:version/groups*/
WITH RECURSIVE "base_and_ancestors" AS (
(
        SELECT
            "namespaces".*
        FROM (( WITH "direct_groups" AS MATERIALIZED (
                    SELECT
                        "namespaces".*
                    FROM (
                        (
                            SELECT
                                "namespaces".*
                            FROM
                                "namespaces"
                                INNER JOIN "members" ON "namespaces"."id" = "members"."source_id"
                            WHERE
                                "members"."type" = 'GroupMember'
                                AND "members"."source_type" = 'Namespace'
                                AND "namespaces"."type" = 'Group'
                                AND "members"."user_id" = 5708766
                                AND "members"."requested_at" IS NULL
                                AND (
                                    access_level >= 10
)
)
                        UNION (
                            SELECT
                                namespaces.*
                            FROM
                                "projects"
                                INNER JOIN "project_authorizations" ON "projects"."id" = "project_authorizations"."project_id"
                                INNER JOIN "namespaces" ON "namespaces"."id" = "projects"."namespace_id"
                            WHERE
                                "project_authorizations"."user_id" = 5708766
)
) namespaces
                    WHERE
                        "namespaces"."type" = 'Group'
)
                    SELECT
                        "namespaces".*
                    FROM (
                        (
                            SELECT
                                "namespaces".*
                            FROM
                                "direct_groups" "namespaces"
                            WHERE
                                "namespaces"."type" = 'Group'
)
                        UNION (
                            SELECT
                                "namespaces".*
                            FROM
                                "namespaces"
                                INNER JOIN "group_group_links" ON "group_group_links"."shared_group_id" = "namespaces"."id"
                            WHERE
                                "namespaces"."type" = 'Group'
                                AND "group_group_links"."shared_with_group_id" IN (
                                    SELECT
                                        "namespaces"."id"
                                    FROM
                                        "direct_groups" "namespaces"
                                    WHERE
                                        "namespaces"."type" = 'Group'
)
)
) namespaces
                        WHERE
                            "namespaces"."type" = 'Group'
)
                    UNION (
                        SELECT
                            "namespaces".*
                        FROM
                            "namespaces"
                            INNER JOIN "members" ON "namespaces"."id" = "members"."source_id"
                        WHERE
                            "members"."type" = 'GroupMember'
                            AND "members"."source_type" = 'Namespace'
                            AND "namespaces"."type" = 'Group'
                            AND "members"."user_id" = 5708766
                            AND "members"."access_level" = 5
                            AND (
                                EXISTS (
                                    SELECT
                                        1
                                    FROM
                                        "plans"
                                        INNER JOIN "gitlab_subscriptions" ON "gitlab_subscriptions"."hosted_plan_id" = "plans"."id"
                                    WHERE
                                        "plans"."name" IN (
                                            'silver', 'premium', 'premium_trial', 'gold', 'ultimate', 'ultimate_trial'
)
                                        AND (
                                            gitlab_subscriptions.namespace_id = namespaces.id
)
)
)
)
) namespaces
                    WHERE
                        "namespaces"."type" = 'Group'
)
                UNION (
                    SELECT
                        "namespaces".*
                    FROM
                        "namespaces",
                        "base_and_ancestors"
                    WHERE
                        "namespaces"."type" = 'Group'
                        AND "namespaces"."id" = "base_and_ancestors"."parent_id"
)
),
            "base_and_descendants" AS (
(
                    SELECT
                        "namespaces".*
                    FROM
                        "namespaces"
                        INNER JOIN "members" ON "namespaces"."id" = "members"."source_id"
                    WHERE
                        "members"."type" = 'GroupMember'
                        AND "members"."source_type" = 'Namespace'
                        AND "namespaces"."type" = 'Group'
                        AND "members"."user_id" = 5708766
                        AND "members"."requested_at" IS NULL
                        AND (access_level >= 10))
                UNION (
                    SELECT
                        "namespaces".*
                    FROM
                        "namespaces",
                        "base_and_descendants"
                    WHERE
                        "namespaces"."type" = 'Group'
                        AND "namespaces"."parent_id" = "base_and_descendants"."id"))
        SELECT
            "namespaces".*
        FROM ((
                SELECT
                    "namespaces".*
                FROM
                    "base_and_ancestors" AS "namespaces"
                WHERE
                    "namespaces"."type" = 'Group')
            UNION (
                SELECT
                    "namespaces".*
                FROM
                    "base_and_descendants" AS "namespaces"
                WHERE
                    "namespaces"."type" = 'Group')) namespaces
    WHERE
        "namespaces"."type" = 'Group'
        AND "namespaces"."id" IN (
            SELECT
                "routes"."source_id"
            FROM
                "routes"
            WHERE
                "routes"."source_type" = 'Namespace'
                AND ("routes"."path" ILIKE '%gitlab%'
                    OR "routes"."name" ILIKE '%gitlab%'))
    ORDER BY
        "namespaces"."name" ASC,
        "namespaces"."id" ASC
    LIMIT 20 OFFSET 0Plan
- Adjust the Groups API endpoint GET /groupsto allow sorting by similarity where exact matches and top level groups are given priority
- Change the frontend Groups API drop down call used in the Search page to send in the new params from the previous step
Release Notes
Edited  by John McGuire