diff --git a/src/mol-model/structure/query/queries/filters.ts b/src/mol-model/structure/query/queries/filters.ts
index a84879bbf472bcc40ecc0f61ea1b52e5afe6f3c6..60c47c06796abf4e4b9f62527e8a00ee30f9bdcd 100644
--- a/src/mol-model/structure/query/queries/filters.ts
+++ b/src/mol-model/structure/query/queries/filters.ts
@@ -9,7 +9,7 @@ import { Unit } from '../../structure';
 import { QueryContext, QueryFn, QueryPredicate } from '../context';
 import { StructureQuery } from '../query';
 import { StructureSelection } from '../selection';
-import { structureAreIntersecting } from '../utils/structure';
+import { structureAreIntersecting } from '../utils/structure-set';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { checkStructureMaxRadiusDistance, checkStructureMinMaxDistance } from '../utils/structure-distance';
 
diff --git a/src/mol-model/structure/query/queries/generators.ts b/src/mol-model/structure/query/queries/generators.ts
index e24ae25892ea88a0fc715c5b45622887827ebb66..9a75838c987f3fedcf344235ddf05570f044fd4c 100644
--- a/src/mol-model/structure/query/queries/generators.ts
+++ b/src/mol-model/structure/query/queries/generators.ts
@@ -14,7 +14,7 @@ import { UnitRing } from '../../structure/unit/rings';
 import Structure from '../../structure/structure';
 import { ElementIndex } from '../../model';
 import { UniqueArray } from 'mol-data/generic';
-import { structureSubtract } from '../utils/structure';
+import { structureSubtract } from '../utils/structure-set';
 
 export const none: StructureQuery = ctx => StructureSelection.Sequence(ctx.inputStructure, []);
 export const all: StructureQuery = ctx => StructureSelection.Singletons(ctx.inputStructure, ctx.inputStructure);
diff --git a/src/mol-model/structure/query/queries/modifiers.ts b/src/mol-model/structure/query/queries/modifiers.ts
index 0756c86f367cf64ae4413293a5c7b22a00ebf854..c249fa266d1d6d5c22a37cbd597e466e8b452250 100644
--- a/src/mol-model/structure/query/queries/modifiers.ts
+++ b/src/mol-model/structure/query/queries/modifiers.ts
@@ -11,6 +11,7 @@ import { StructureSelection } from '../selection';
 import { UniqueStructuresBuilder } from '../utils/builders';
 import { StructureUniqueSubsetBuilder } from '../../structure/util/unique-subset-builder';
 import { QueryContext } from '../context';
+import { structureIntersect, structureSubtract } from '../utils/structure-set';
 
 function getWholeResidues(ctx: QueryContext, source: Structure, structure: Structure) {
     const builder = source.subsetBuilder(true);
@@ -39,7 +40,7 @@ function getWholeResidues(ctx: QueryContext, source: Structure, structure: Struc
     return builder.getStructure();
 }
 
-export function wholeResidues(query: StructureQuery, isFlat: boolean): StructureQuery {
+export function wholeResidues(query: StructureQuery): StructureQuery {
     return ctx => {
         const inner = query(ctx);
         if (StructureSelection.isSingleton(inner)) {
@@ -54,9 +55,6 @@ export function wholeResidues(query: StructureQuery, isFlat: boolean): Structure
     };
 }
 
-
-// export function groupBy()  ...
-
 export interface IncludeSurroundingsParams {
     radius: number,
     // TODO
@@ -112,9 +110,55 @@ export function querySelection(selection: StructureQuery, query: StructureQuery)
             StructureSelection.forEach(query(ctx), add);
             ctx.popInputStructure();
             if (sI % 10 === 0) ctx.throwIfTimedOut();
-        })
+        });
         return ret.getSelection();
     }
 }
 
-// TODO: intersectBy, exceptBy, unionBy, union, cluster, includeConnected
\ No newline at end of file
+export function intersectBy(query: StructureQuery, by: StructureQuery): StructureQuery {
+    return ctx => {
+        const selection = query(ctx);
+        if (StructureSelection.structureCount(selection) === 0) return selection;
+
+        const bySel = by(ctx);
+        if (StructureSelection.structureCount(bySel) === 0) return StructureSelection.Empty(ctx.inputStructure);
+        const unionBy = StructureSelection.unionStructure(bySel);
+
+        const ret = StructureSelection.UniqueBuilder(ctx.inputStructure);
+        StructureSelection.forEach(selection, (s, sI) => {
+            const ii = structureIntersect(unionBy, s);
+            if (ii.elementCount !== 0) ret.add(ii);
+        });
+
+        return ret.getSelection();
+    };
+}
+
+export function exceptBy(query: StructureQuery, by: StructureQuery): StructureQuery {
+    return ctx => {
+        const selection = query(ctx);
+        if (StructureSelection.structureCount(selection) === 0) return selection;
+
+        const bySel = by(ctx);
+        if (StructureSelection.structureCount(bySel) === 0) return StructureSelection.Empty(ctx.inputStructure);
+        const subtractBy = StructureSelection.unionStructure(bySel);
+
+        const ret = StructureSelection.UniqueBuilder(ctx.inputStructure);
+        StructureSelection.forEach(selection, (s, sI) => {
+            const diff = structureSubtract(s, subtractBy);
+            if (diff.elementCount !== 0) ret.add(diff);
+        });
+
+        return ret.getSelection();
+    };
+}
+
+export function union(query: StructureQuery): StructureQuery {
+    return ctx => {
+        const ret = StructureSelection.LinearBuilder(ctx.inputStructure);
+        ret.add(StructureSelection.unionStructure(query(ctx)));
+        return ret.getSelection();
+    };
+}
+
+// TODO: unionBy (skip this one?), cluster, includeConnected, includeSurroundings with "radii", expandProperty
\ No newline at end of file
diff --git a/src/mol-model/structure/query/selection.ts b/src/mol-model/structure/query/selection.ts
index c4c804faf09442cdc53c9b9bbf82da31a5c2f177..650c0ae04e23685be2d770b73672df57d7755b74 100644
--- a/src/mol-model/structure/query/selection.ts
+++ b/src/mol-model/structure/query/selection.ts
@@ -6,7 +6,7 @@
 
 import { HashSet } from 'mol-data/generic'
 import { Structure, StructureElement, Unit } from '../structure'
-import { structureUnion } from './utils/structure';
+import { structureUnion } from './utils/structure-set';
 import { OrderedSet, SortedArray } from 'mol-data/int';
 
 // A selection is a pair of a Structure and a sequence of unique AtomSets
diff --git a/src/mol-model/structure/query/utils/builders.ts b/src/mol-model/structure/query/utils/builders.ts
index c27ff79ef55e6c3b4dcc99ed3f9dab56e76079f4..9da400cba184893cda559a225bd966b26357b5f1 100644
--- a/src/mol-model/structure/query/utils/builders.ts
+++ b/src/mol-model/structure/query/utils/builders.ts
@@ -7,7 +7,7 @@
 import { StructureElement, Structure } from '../../structure';
 import { StructureSelection } from '../selection';
 import { HashSet } from 'mol-data/generic';
-import { structureUnion } from './structure';
+import { structureUnion } from './structure-set';
 import { StructureSubsetBuilder } from '../../structure/util/subset-builder';
 import { ElementIndex } from '../../model';
 
diff --git a/src/mol-model/structure/query/utils/structure.ts b/src/mol-model/structure/query/utils/structure-set.ts
similarity index 100%
rename from src/mol-model/structure/query/utils/structure.ts
rename to src/mol-model/structure/query/utils/structure-set.ts