group_by
Organize database records by grouping them based on a specific column and calculate counts for each group to analyze data patterns and distributions.
Instructions
Group records by a column and get counts
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| base_id | Yes | The ID of the base/project | |
| table_name | Yes | The name of the table | |
| column_name | Yes | The column to group by | |
| where | No | Optional filter condition | |
| sort | No | Sort order for groups | |
| limit | No | Maximum number of groups to return | |
| offset | No | Number of groups to skip |
Implementation Reference
- src/tools/query.ts:177-205 (handler)Handler function that executes the group_by tool logic by calling the NocoDB client's groupBy method with user-provided arguments and formatting the response.handler: async ( client: NocoDBClient, args: { base_id: string; table_name: string; column_name: string; where?: string; sort?: string; limit?: number; offset?: number; }, ) => { const groups = await client.groupBy( args.base_id, args.table_name, args.column_name, { where: args.where, sort: args.sort, limit: args.limit, offset: args.offset, }, ); return { groups, count: groups.length, column: args.column_name, }; },
- src/tools/query.ts:143-176 (schema)Input schema defining the parameters for the group_by tool, including required base_id, table_name, column_name, and optional where, sort, limit, offset.inputSchema: { type: "object", properties: { base_id: { type: "string", description: "The ID of the base/project", }, table_name: { type: "string", description: "The name of the table", }, column_name: { type: "string", description: "The column to group by", }, where: { type: "string", description: "Optional filter condition", }, sort: { type: "string", description: "Sort order for groups", }, limit: { type: "number", description: "Maximum number of groups to return", }, offset: { type: "number", description: "Number of groups to skip", }, }, required: ["base_id", "table_name", "column_name"], },
- src/tools/query.ts:140-207 (registration)The group_by tool object definition, including name, description, schema, and handler, exported as part of queryTools array.{ name: "group_by", description: "Group records by a column and get counts", inputSchema: { type: "object", properties: { base_id: { type: "string", description: "The ID of the base/project", }, table_name: { type: "string", description: "The name of the table", }, column_name: { type: "string", description: "The column to group by", }, where: { type: "string", description: "Optional filter condition", }, sort: { type: "string", description: "Sort order for groups", }, limit: { type: "number", description: "Maximum number of groups to return", }, offset: { type: "number", description: "Number of groups to skip", }, }, required: ["base_id", "table_name", "column_name"], }, handler: async ( client: NocoDBClient, args: { base_id: string; table_name: string; column_name: string; where?: string; sort?: string; limit?: number; offset?: number; }, ) => { const groups = await client.groupBy( args.base_id, args.table_name, args.column_name, { where: args.where, sort: args.sort, limit: args.limit, offset: args.offset, }, ); return { groups, count: groups.length, column: args.column_name, }; }, }, ];
- src/index.ts:55-62 (registration)Top-level registration where queryTools (including group_by) is combined into allTools for MCP server tool list and call handlers.const allTools = [ ...databaseTools, ...tableTools, ...recordTools, ...viewTools, ...queryTools, ...attachmentTools, ];
- src/nocodb-api.ts:375-413 (helper)Underlying helper method in NocoDBClient that performs client-side grouping by fetching records, counting occurrences per value, applying sort/limit/offset.async groupBy( baseId: string, tableName: string, columnName: string, options?: QueryOptions, ): Promise<any[]> { // Implement client-side grouping const records = await this.listRecords(baseId, tableName, options); const groups = new Map<any, number>(); records.list.forEach((record) => { const value = record[columnName]; groups.set(value, (groups.get(value) || 0) + 1); }); const result = Array.from(groups.entries()).map(([value, count]) => ({ [columnName]: value, count, })); // Apply sorting if specified if (options?.sort) { const sortField = Array.isArray(options.sort) ? options.sort[0] : options.sort; const desc = sortField.startsWith("-"); result.sort((a, b) => { const aVal = a[columnName]; const bVal = b[columnName]; return desc ? (bVal > aVal ? 1 : -1) : aVal > bVal ? 1 : -1; }); } // Apply limit and offset const start = options?.offset || 0; const end = options?.limit ? start + options.limit : undefined; return result.slice(start, end); }