{"record":{"id":"06a38a6d369d7c27","repo":"litedb-org/LiteDB","slug":"group-by-expression-do-not-support-include","errorCode":null,"errorMessage":"GROUP BY expression do not support INCLUDE","messagePattern":"GROUP BY expression do not support INCLUDE","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"LiteDB/Engine/Query/QueryOptimization.cs","lineNumber":563,"sourceCode":"\n                if (orderBy.Segments.Count == 1)\n                {\n                    orderBy = null;\n                }\n            }\n\n            // otherwise, query.OrderBy will be set according user defined\n            _queryPlan.OrderBy = orderBy;\n        }\n\n        /// <summary>\n        /// Define GroupBy optimization (try re-use index)\n        /// </summary>\n        private void DefineGroupBy()\n        {\n            if (_query.GroupBy == null) return;\n\n            if (_query.Includes.Count > 0) throw new NotSupportedException(\"GROUP BY expression do not support INCLUDE\");\n\n            var expression = _query.GroupBy;\n            var select = _queryPlan.Select.Expression;\n            var having = _query.Having;\n            var groupOrderBy = (OrderBy)null;\n\n            // if groupBy use same expression in index, no additional ordering is required before grouping\n            if (expression.Source == _queryPlan.IndexExpression)\n            {\n                // index already provides grouped ordering\n            }\n            else\n            {\n                // create orderBy expression\n                groupOrderBy = new OrderBy(new[] { new OrderByItem(expression, Query.Ascending) });\n            }\n\n            _queryPlan.GroupBy = new GroupBy(expression, select, having, groupOrderBy);","sourceCodeStart":545,"sourceCodeEnd":581,"githubUrl":"https://github.com/litedb-org/LiteDB/blob/f906a5f850678719e39a39a006cb66dcae563cfa/LiteDB/Engine/Query/QueryOptimization.cs#L545-L581","documentation":"Thrown by QueryOptimization.DefineGroupBy when a query combines GROUP BY with one or more INCLUDE clauses. Grouping aggregates rows into buckets, which is semantically incompatible with INCLUDE (which expands related documents per source row). The optimizer rejects this combination early during query planning with a NotSupportedException rather than producing ambiguous results.","triggerScenarios":"Calling ILiteCollection.Query().Include(\"$.related\").GroupBy(\"$.key\") or SQL like 'SELECT $.key, COUNT(*) FROM col GROUP BY $.key INCLUDE $.related'. Any query where _query.GroupBy != null and _query.Includes.Count > 0.","commonSituations":"Trying to eagerly load related documents in an aggregation query; building a generic query builder that always applies Include and also supports GroupBy; migrating an include-heavy query to grouped form.","solutions":["Remove the Include(s) from any GROUP BY query; fetch related documents in a separate query after grouping.","Perform the join/include in application code after obtaining the grouped results.","If you need per-row expansion, drop GROUP BY and aggregate in code.","Split into two queries: one grouped, one include-expanded over the grouped keys."],"exampleFix":"// before — GROUP BY + INCLUDE\nvar results = col.Query()\n    .Include(\"$.author\")\n    .GroupBy(\"$.category\")\n    .Select(\"{ cat: $.category, n: COUNT(*) }\")\n    .ToList(); // throws\n\n// after — separate the concerns\nvar grouped = col.Query()\n    .GroupBy(\"$.category\")\n    .Select(\"{ cat: $.category, n: COUNT(*) }\")\n    .ToList();\n// fetch includes per-row in a different (non-grouped) query if needed","handlingStrategy":"validation","validationCode":"public List<BsonDocument> GroupedQuery(ILiteCollection<BsonDocument> col, string groupBy, string select)\n{\n    // Reject Include + GroupBy combinations before they reach the optimizer.\n    // (No public flag to check includes count; enforce at the builder layer.)\n    var query = col.Query();\n    // Do NOT call .Include(...) here if you will .GroupBy(...).\n    return query.GroupBy(groupBy).Select(select).ToList();\n}","typeGuard":"static bool IsCompatibleWithGroupBy(ILiteCollection<BsonDocument> col) =>\n    true; // Enforced by NOT chaining Include before GroupBy.","tryCatchPattern":"try\n{\n    var r = col.Query().Include(\"$.rel\").GroupBy(\"$.key\").Select(s).ToList();\n}\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"GROUP BY expression do not support INCLUDE\"))\n{\n    // Remove the Include and fetch related data in a separate query.\n    throw new ArgumentException(\"GROUP BY cannot be combined with INCLUDE. Split into separate queries.\", ex);\n}","preventionTips":["Never chain Include() before GroupBy() in the same query.","Fetch related documents in a separate non-grouped query.","In query builders, treat Include and GroupBy as mutually exclusive.","Aggregate in application code if per-row includes are essential."],"tags":["query","groupby","include","bson-expression","litedb-engine"],"backgroundTag":null,"analyzedSha":"f906a5f850678719e39a39a006cb66dcae563cfa","analyzedAt":"2026-08-13T21:56:30.148Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}