diff --git a/src/queryExecution/sql/queryConverterSql.ts b/src/queryExecution/sql/queryConverterSql.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6d91a1d313aa97f1a953666bf9986b130789c247
--- /dev/null
+++ b/src/queryExecution/sql/queryConverterSql.ts
@@ -0,0 +1,284 @@
+import type { AllLogicStatement, AnyStatement, BackendQueryFormat, NodeStruct, QueryStruct } from 'ts-common';
+import type { QueryText } from '../model';
+import { extractLogicSQL } from './convertLogicToSQL';
+import type { QueryCacheData } from '../cypher/converter/model';
+
+function cleanStringOfNewLinesAndTabs(str: string): string {
+  if (!str) {
+    return '';
+  }
+  let trimmedSQL = str.replace(/\n/g, ' ');
+  trimmedSQL = trimmedSQL.replaceAll(/ {2,50}/g, ' ');
+  trimmedSQL = trimmedSQL.replace(/\t+/g, '');
+  return trimmedSQL.trim();
+}
+
+// function buildNodeCTE(path: QueryStruct, logic: AnyStatement | undefined): { node: string; edges: string; rows: string[] } {
+//   const node = path.node;
+//   const pathId = path.id;
+
+//   if (!node || !node.label || !node.id) {
+//     return { node: '', edges: '', rows: [] };
+//   }
+
+//   const loopThoughNodes = (node: NodeStruct): NodeStruct[] => {
+//     if (node.relation && node.relation.node) {
+//       return [node, ...loopThoughNodes(node.relation.node)];
+//     }
+//     return [node];
+//   };
+//   const allNodes = loopThoughNodes(node);
+
+//   const where = logic ? extractLogicSQL(logic, { nodes: allNodes }).logic : undefined;
+//   const rowList = allNodes.map(n => `${n.id}_row`);
+//   const select = `
+//   SELECT ${[
+//     ...allNodes.map(n => `to_jsonb(${n.id}) AS ${n.id}_row`),
+//     ...allNodes
+//       .filter(n => n.relation && n!.relation!.node)
+//       .map(
+//         n =>
+//           `${n.id}.${n!.relation!.label!.split('.')[0]}::text AS ${n.id}_${n!.relation!.label!.split('.')[0]}, ${n!.relation!.node!.id}.${
+//             n!.relation!.label!.split('.')[1]
+//           }::text AS ${n!.relation!.node!.id}_${n!.relation!.label!.split('.')[1]}`,
+//       ),
+//   ].join(', ')}
+//   FROM ${node.label} ${node.id}
+//   ${allNodes
+//     .filter(n => n?.relation?.node?.label && n?.relation?.node?.id)
+//     .map(
+//       n =>
+//         `INNER JOIN ${n!.relation!.node!.label} ${n!.relation!.node!.id} ON ${n.id}.${n!.relation!.label!.split('.')[0]}::text = ${
+//           n!.relation!.node!.id
+//         }.${n!.relation!.label!.split('.')[1]}::text`,
+//     )
+//     .join('\n')}
+//     ${where ? `WHERE ${where}` : ''}`;
+
+//   const edges = buildEdgesCTE(node, rowList, pathId).join(' UNION ALL ');
+
+//   return { node: select, edges, rows: rowList };
+// }
+
+// function buildEdgesCTE(node: NodeStruct | undefined, rowList: string[], pathId: string): string[] {
+//   if (!node || !node.relation || !node.relation.node || !node.id || !node.relation.node.id || !node.relation.label) {
+//     return [];
+//   }
+
+//   const edge = `
+//   SELECT jsonb_build_object(
+//     '_id', concat('${node.label}-', ${node.id}_${node.relation.label.split('.')[0]}::text, '-${node.relation.node.label}-', ${
+//     node.relation.node.id
+//   }_${node.relation.label.split('.')[1]}::text),
+//     'label', '${node.relation.label}',
+//     'attributes', '{}'::jsonb,
+//     'from', ${node.id}_${node.relation.label.split('.')[0]}::text,
+//     'to', ${node.relation.node.id}_${node.relation.label.split('.')[1]}::text
+//   ) AS edge,
+//   ${rowList.join(',\n')}
+//   FROM ${pathId}`;
+
+//   const ret = cleanStringOfNewLinesAndTabs(edge);
+//   return [ret, ...buildEdgesCTE(node.relation.node, rowList, pathId)];
+// }
+
+// function buildNodeCountsCTE(node: NodeStruct | undefined): string[] {
+//   if (!node || !node.label || !node.id) {
+//     return [];
+//   }
+//   const nodeParts: string[] = [];
+//   const mainNode = `SELECT '${node.label}' AS label FROM ${node.label}`;
+//   nodeParts.push(cleanStringOfNewLinesAndTabs(mainNode));
+//   buildNodeCountsCTE(node.relation?.node).forEach(part => nodeParts.push(part));
+//   return nodeParts;
+// }
+
+// function buildEdgeCountsCTE(node: NodeStruct | undefined): string[] {
+//   if (!node || !node.relation || !node.relation.node || !node.id || !node.relation.node.id || !node.relation.label) {
+//     return [];
+//   }
+
+//   const edge = `
+//   SELECT '${node.relation.label}' AS label, COUNT(*) AS count
+//   FROM ${node.label} ${node.id}
+//   JOIN ${node.relation.node.label} ${node.relation.node.id}
+//   ON ${node.id}.${node.relation.label.split('.')[0]} = ${node.relation.node.id}.${node.relation.label.split('.')[1]}
+//   GROUP BY label`;
+//   const ret = cleanStringOfNewLinesAndTabs(edge);
+//   return [ret, ...buildEdgeCountsCTE(node.relation.node)];
+// }
+
+export function query2SQL(query: BackendQueryFormat): QueryText {
+  const loopThoughNodes = (node: NodeStruct): NodeStruct[] => {
+    if (node.relation && node.relation.node) {
+      return [node, ...loopThoughNodes(node.relation.node)];
+    }
+    return [node];
+  };
+  const allNodes = query.query.flatMap(path => loopThoughNodes(path.node));
+  const allUniqueNodes: Record<
+    string,
+    { label: string; joins: { from: string; leftJoin: string; rightJoin: string; to: string; fromLabel: string; toLabel: string }[] }
+  > = Object.fromEntries(
+    allNodes
+      .map(n => [n.id, { label: n.label, joins: [] }])
+      .filter((node, index, self) => {
+        return index === self.findIndex(t => t[0] === node[0] && t[1] === node[1]);
+      }),
+  );
+  allNodes.forEach(n => {
+    if (n.id && n.relation && n.relation.node && n.relation.node.id && n.label && n.relation.node.label) {
+      allUniqueNodes[n.id].joins.push({
+        from: n.id,
+        leftJoin: n!.relation!.label!.split('.')[0],
+        rightJoin: n!.relation!.label!.split('.')[1],
+        to: n!.relation!.node!.id,
+        fromLabel: n!.label,
+        toLabel: n!.relation!.node!.label,
+      });
+    }
+  });
+
+  console.log(JSON.stringify(allNodes, null, 2));
+
+  const nodeEntries = Object.entries(allUniqueNodes);
+  const where = query.logic ? extractLogicSQL(query.logic, { nodes: allNodes }).logic : undefined;
+
+  const firstNode = nodeEntries[0][1];
+
+  const relIDSql = Object.values(allUniqueNodes)
+    .map(n =>
+      n.joins.map(j => `${j.from}.${j.leftJoin} AS ${j.from}_${j.leftJoin}, ${j.to}.${j.rightJoin} AS ${j.to}_${j.rightJoin}`).join(', '),
+    )
+    .filter(s => s.length > 0);
+  const select = [...nodeEntries.map(n => `to_jsonb(${n[0]}) AS ${n[0]}_row`), ...relIDSql].join(', ');
+
+  let sql = `SELECT ${select} FROM ${firstNode.label} ${nodeEntries[0][0]}`;
+  // let sql = `SELECT jsonb_agg(row_to_json(t)) FROM ${firstNode.label} ${nodeEntries[0][0]}`;
+
+  let joins = '';
+  for (let i = 0; i < nodeEntries.length; i++) {
+    const [nodeId, node] = nodeEntries[i];
+    if (node.joins) {
+      node.joins.forEach(j => {
+        joins += ` INNER JOIN ${allUniqueNodes[j.to].label} ${j.to} ON ${j.from}.${j.leftJoin}::text = ${j.to}.${j.rightJoin}::text`;
+      });
+    }
+  }
+
+  sql += joins;
+  sql += where ? ` WHERE ${where}` : '';
+  const sqlNoLimit = sql;
+  sql += query.limit ? ` LIMIT ${query.limit}` : '';
+
+  const nodes_cte = `SELECT jsonb_agg(row_to_json(t)) AS nodes FROM (${nodeEntries
+    .map(n => `SELECT DISTINCT ${n[0]}_row AS node FROM combined`)
+    .join(' UNION ALL ')}) AS t`;
+
+  const allUniqueEdges = Object.values(allUniqueNodes)
+    .map(n =>
+      n.joins
+        .map(j => {
+          return `SELECT jsonb_build_object(
+          '_id', concat('${n.label}-', md5(${j.from}_row::text), '-${allUniqueNodes[j.to].label}-', md5(${j.to}_row::text)),
+          'label', '${j.leftJoin}.${j.rightJoin}',
+          'attributes', '{}'::jsonb,
+          'from', md5(${j.from}_row::text),
+          'to', md5(${j.to}_row::text)
+        ) AS edge
+        FROM combined`;
+        })
+        .filter(s => s.length > 0)
+        .join(' UNION ALL '),
+    )
+    .filter(s => s.length > 0)
+    .join(' UNION ALL ');
+
+  // console.log(JSON.stringify(allUniqueNodes, null, 2));
+  // const rowList = allNodes.map(n => `${n.id}_row`);
+  // const select = `
+  // SELECT ${allNodes.map(n => `to_jsonb(${n.id}) AS ${n.id}_row`).join(', ')},
+  // ${allNodes
+  //   .filter(n => n.relation && n!.relation!.node)
+  //   .map(
+  //     n =>
+  //       `${n.id}.${n!.relation!.label!.split('.')[0]}::text AS ${n.id}_${n!.relation!.label!.split('.')[0]}, ${n!.relation!.node!.id}.${
+  //         n!.relation!.label!.split('.')[1]
+  //       }::text AS ${n!.relation!.node!.id}_${n!.relation!.label!.split('.')[1]}`,
+  //   )
+  //   .join(', ')}
+  // FROM ${node.label} ${node.id}
+  // ${allNodes
+  //   .filter(n => n?.relation?.node?.label && n?.relation?.node?.id)
+  //   .map(
+  //     n =>
+  //       `INNER JOIN ${n!.relation!.node!.label} ${n!.relation!.node!.id} ON ${n.id}.${n!.relation!.label!.split('.')[0]}::text = ${
+  //         n!.relation!.node!.id
+  //       }.${n!.relation!.label!.split('.')[1]}::text`,
+  //   )
+  //   .join('\n')}
+  //   ${where ? `WHERE ${where}` : ''}`;
+
+  // const edges = buildEdgesCTE(node, rowList, pathId).join(' UNION ALL ');
+
+  // const nodesCTE = query.query.flatMap(path => ({ ...buildNodeCTE(path, query.logic), path: path }));
+  // const nodeCountsCTE = [...new Set(query.query.flatMap(path => buildNodeCountsCTE(path.node)))];
+  // const edgeCountsCTE = [...new Set(query.query.flatMap(path => buildEdgeCountsCTE(path.node)))];
+
+  const mainQuery = `WITH combined AS (${sql}),
+    nodes_cte AS (
+      SELECT jsonb_agg(row_to_json(t)) AS nodes FROM (${nodeEntries
+        .map(
+          ([nodeId, node]) => `
+          SELECT 
+            md5(${nodeId}_row::text) AS _id,
+            '${node.label}' AS label,
+            ${nodeId}_row - 'id' AS attributes
+          FROM combined`,
+        )
+        .join(' UNION ALL ')}) AS t
+    ),
+    edges_cte AS (
+      SELECT jsonb_agg(edge) AS edges
+        FROM (
+          ${allUniqueEdges.length > 0 ? allUniqueEdges : 'SELECT null AS edge WHERE FALSE'}
+        ) AS e
+    ),
+    node_counts AS (
+      SELECT jsonb_agg(jsonb_build_object('label', label, 'count', count)) AS nodeCounts
+      FROM (
+        SELECT label, COUNT(*) AS count
+        FROM (
+          ${[...new Set(nodeEntries.map(([_, node]) => node.label))]
+            .map(label => `SELECT '${label}' AS label FROM ${label}`)
+            .join(' UNION ALL ')}
+        ) AS node_labels
+        GROUP BY label
+      ) AS counts
+    )
+    SELECT jsonb_build_object(
+      'nodes', nodes_cte.nodes,
+      'edges', COALESCE(edges_cte.edges, '[]'::jsonb),
+      'nodeCounts', COALESCE((SELECT nodeCounts FROM node_counts), '[]'::jsonb)
+    ) AS result FROM nodes_cte, edges_cte;`;
+
+  // 'nodeCounts', COALESCE( (SELECT jsonb_agg(jsonb_build_object('label', label, 'count', count))
+  //   FROM node_counts), '[]'::jsonb ),
+  // 'edgeCounts', COALESCE( (SELECT jsonb_agg(jsonb_build_object('label', label, 'count', count))
+  //   FROM edge_counts), '[]'::jsonb )
+  // node_counts AS (
+  //   SELECT label, COUNT(*) AS count
+  //   FROM (
+  //     ${nodesCTE.map(node => node.node).join(' UNION ALL ')}
+  //   ) t
+  //   GROUP BY label
+  // ),
+  // edge_counts AS (
+  //   ${nodesCTE.map(node => node.edges).join(' UNION ALL ')}
+  // )
+
+  return {
+    query: cleanStringOfNewLinesAndTabs(mainQuery),
+    countQuery: '',
+  };
+}
diff --git a/src/utils/cypher/converter/logic.ts b/src/utils/cypher/converter/logic.ts
index 4ef8a20d99ef05f57ee9f73d7259d90a3eeaf4c0..9d6a2133e94f75ab9d25e72050586118bf7b02d7 100644
--- a/src/utils/cypher/converter/logic.ts
+++ b/src/utils/cypher/converter/logic.ts
@@ -1,6 +1,9 @@
-import { StringFilterTypes, type AnyStatement } from 'ts-common/src/model/query/logic/general';
+import { type AllLogicStatement, type AnyStatement } from 'ts-common/src/model/query/logic/general';
 import type { QueryCacheData } from './model';
 import { log } from 'ts-common/src/logger/logger';
+import { NumberAggregationTypes, NumberFilterTypes, NumberFunctionTypes } from 'ts-common/src/model/query/logic/number';
+import { StringFilterTypes, StringFunctionTypes } from 'ts-common/src/model/query/logic/string';
+import { DateFilterTypes, DateFunctionTypes } from 'ts-common/src/model/query/logic/date/types';
 
 export function createWhereLogic(
   op: string,
@@ -8,7 +11,8 @@ export function createWhereLogic(
   whereLogic: Set<string>,
   cacheData: QueryCacheData,
 ): { logic: string; where: Set<string> } {
-  const newWhereLogic = `${left.replace('.', '_')}_${op}`;
+  const newOp = op.replace('_', '').toLowerCase();
+  const newWhereLogic = `${left.replace('.', '_')}_${newOp}`;
 
   // TODO: Relation temporarily ignored due to unnecessary added complexity in the query
   // for (const relation of cacheData.relations) {
@@ -17,7 +21,7 @@ export function createWhereLogic(
   //     }
   // }
 
-  whereLogic.add(`${op}(${left}) AS ${newWhereLogic}`);
+  whereLogic.add(`${newOp}(${left}) AS ${newWhereLogic}`);
   for (const entity of cacheData.entities) {
     if (entity.id !== left) {
       whereLogic.add(entity.id);
@@ -31,24 +35,28 @@ export function extractLogicCypher(logicQuery: AnyStatement, cacheData: QueryCac
   switch (typeof logicQuery) {
     case 'object':
       if (Array.isArray(logicQuery)) {
-        let op = logicQuery[0].replace('_', '').toLowerCase();
-        let right = logicQuery?.[2];
+        const op = logicQuery[0];
+        let newOp: string = op;
+        const right = logicQuery?.[2];
         const { logic: left, where: whereLogic } = extractLogicCypher(logicQuery[1], cacheData);
 
         switch (op) {
-          case '!=':
-            op = '<>';
+          case NumberFilterTypes.EQUAL:
+          case StringFilterTypes.EQUAL:
+          case DateFilterTypes.EQUAL:
+            newOp = '=';
             break;
-          case '==':
-            if (right === '".*"') op = '=~'; // in case "equals to <empty string>", this is what happens
-            else op = '=';
+          case NumberFilterTypes.NOT_EQUAL:
+          case StringFilterTypes.NOT_EQUAL:
+          case DateFilterTypes.NOT_EQUAL:
+            if (right === '".*"') newOp = '=~'; // in case "equals to <empty string>", this is what happens
+            else newOp = '<>';
             break;
-          case 'like':
-            op = '=~';
+          case StringFilterTypes.LIKE:
+            newOp = '=~';
             break;
-          case 'in':
-          case 'present in list':
-            op = 'IN';
+          case StringFilterTypes.IN:
+            newOp = 'IN';
             if (typeof right === 'string') {
               return {
                 logic: `(${left} IN [${right
@@ -60,9 +68,8 @@ export function extractLogicCypher(logicQuery: AnyStatement, cacheData: QueryCac
               };
             }
             break;
-          case 'not in':
-          case 'not in list':
-            op = 'NOT IN';
+          case StringFilterTypes.NOT_IN:
+            newOp = 'NOT IN';
             if (typeof right === 'string') {
               return {
                 logic: `(NOT ${left} IN [${right
@@ -74,20 +81,34 @@ export function extractLogicCypher(logicQuery: AnyStatement, cacheData: QueryCac
               };
             }
             break;
-          case 'isempty':
+          case StringFilterTypes.EMPTY:
             return { logic: `(${left} IS NULL OR ${left} = "")`, where: whereLogic };
-          case 'isnotempty':
+          case StringFilterTypes.NOT_EMPTY:
             return { logic: `(${left} IS NOT NULL AND ${left} <> "")`, where: whereLogic };
-          case 'lower':
+          case StringFunctionTypes.LOWER:
             return { logic: `toLower(${left})`, where: whereLogic };
-          case 'upper':
+          case StringFunctionTypes.UPPER:
             return { logic: `toUpper(${left})`, where: whereLogic };
-          case 'avg':
-          case 'count':
-          case 'max':
-          case 'min':
-          case 'sum':
+          case NumberAggregationTypes.AVG:
+          case NumberAggregationTypes.COUNT:
+          case NumberAggregationTypes.MAX:
+          case NumberAggregationTypes.MIN:
+          case NumberAggregationTypes.SUM:
             return createWhereLogic(op, left, whereLogic, cacheData);
+          case DateFunctionTypes.YEAR:
+            return { logic: `${left}.year`, where: whereLogic };
+          case DateFunctionTypes.MONTH:
+            return { logic: `${left}.month`, where: whereLogic };
+          case DateFunctionTypes.DAY:
+            return { logic: `${left}.day`, where: whereLogic };
+          case DateFunctionTypes.HOUR:
+            return { logic: `${left}.hour`, where: whereLogic };
+          case DateFunctionTypes.MINUTE:
+            return { logic: `${left}.minute`, where: whereLogic };
+          case DateFunctionTypes.SECOND:
+            return { logic: `${left}.seconds`, where: whereLogic };
+          case DateFunctionTypes.DAY_OF_WEEK:
+            return { logic: `${left}.weekDay`, where: whereLogic };
         }
         if (logicQuery.length > 2 && logicQuery[2]) {
           const { logic: rightLogic, where: whereLogicRight } = extractLogicCypher(logicQuery[2], cacheData);
@@ -96,12 +117,12 @@ export function extractLogicCypher(logicQuery: AnyStatement, cacheData: QueryCac
           for (const where of whereLogicRight) {
             whereLogic.add(where);
           }
-          if (op === '=~') {
+          if (newOp === '=~') {
             rightMutable = `(".*" + ${rightMutable} + ".*")`;
           }
-          return { logic: `(${left} ${op} ${rightMutable})`, where: whereLogic };
+          return { logic: `(${left} ${newOp.replace('_', '').toLowerCase()} ${rightMutable})`, where: whereLogic };
         }
-        return { logic: `(${op} ${left})`, where: whereLogic };
+        return { logic: `(${newOp.replace('_', '').toLowerCase()} ${left})`, where: whereLogic };
       }
       return { logic: logicQuery, where: new Set() };
     case 'string':
diff --git a/src/utils/cypher/converter/queryConverter.test.ts b/src/utils/cypher/converter/queryConverter.test.ts
index 5227c6cd6ed1d867142f8bacd4718795b3702f23..de23cf8b38867e3ada042d49f2aa358c50b12b6a 100644
--- a/src/utils/cypher/converter/queryConverter.test.ts
+++ b/src/utils/cypher/converter/queryConverter.test.ts
@@ -1,6 +1,8 @@
+import type { BackendQueryFormat } from 'ts-common';
+import { StringFilterTypes, StringFunctionTypes } from 'ts-common/src/model/query/logic/string';
 import { query2Cypher } from './queryConverter';
-import { StringFilterTypes, type BackendQueryFormat } from 'ts-common';
 import { expect, test, describe, it } from 'bun:test';
+import { NumberAggregationTypes, NumberFilterTypes, NumberFunctionTypes } from 'ts-common/src/model/query/logic/number';
 
 function fixCypherSpaces(cypher?: string | null): string {
   if (!cypher) {
@@ -71,7 +73,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       return: ['*'],
-      logic: ['!=', '@p1.name', '"Raymond Campbell"'],
+      logic: [NumberFilterTypes.NOT_EQUAL, '@p1.name', '"Raymond Campbell"'],
       query: [
         {
           id: 'path1',
@@ -122,7 +124,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       limit: 5000,
-      logic: ['And', ['<', '@movie.imdbRating', 7.5], ['==', 'p2.age', 'p1.age']],
+      logic: ['And', [NumberFilterTypes.LESS_THAN, '@movie.imdbRating', 7.5], [NumberFilterTypes.EQUAL, 'p2.age', 'p1.age']],
       query: [
         {
           id: 'path1',
@@ -165,7 +167,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       limit: 5000,
-      logic: ['<', ['-', '@movie.year', 'p1.year'], 10],
+      logic: [NumberFilterTypes.LESS_THAN, [NumberFunctionTypes.SUBTRACT, '@movie.year', 'p1.year'], 10],
       query: [
         {
           id: 'path1',
@@ -199,7 +201,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       limit: 5000,
-      logic: ['And', ['<', '@movie.imdbRating', 7.5], ['==', 'p2.age', 'p1.age']],
+      logic: ['And', [NumberFilterTypes.LESS_THAN, '@movie.imdbRating', 7.5], [NumberFilterTypes.EQUAL, 'p2.age', 'p1.age']],
       query: [
         {
           id: 'path1',
@@ -238,7 +240,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       limit: 5000,
-      logic: ['<', '@p1.age', ['Avg', '@p1.age']],
+      logic: [NumberFilterTypes.LESS_THAN, '@p1.age', [NumberAggregationTypes.AVG, '@p1.age']],
       query: [
         {
           id: 'path1',
@@ -275,7 +277,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       limit: 5000,
-      logic: ['<', '@p1.age', ['Avg', '@p1.age']],
+      logic: [NumberFilterTypes.LESS_THAN, '@p1.age', [NumberAggregationTypes.AVG, '@p1.age']],
       query: [
         {
           id: 'path1',
@@ -330,7 +332,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       limit: 5000,
-      logic: ['Like', ['Lower', '@p1.name'], '"john"'],
+      logic: [StringFilterTypes.LIKE, [StringFunctionTypes.LOWER, '@p1.name'], '"john"'],
       query: [
         {
           id: 'path1',
@@ -355,7 +357,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       limit: 500,
-      logic: ['Like', '@id_1691576718400.title', '"ale"'],
+      logic: [StringFilterTypes.LIKE, '@id_1691576718400.title', '"ale"'],
       query: [
         {
           id: 'path_0',
@@ -386,7 +388,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       limit: 500,
-      logic: ['Like', '@id_1691576718400.title', '"ale"'],
+      logic: [StringFilterTypes.LIKE, '@id_1691576718400.title', '"ale"'],
       query: [
         {
           id: 'path_0',
@@ -417,7 +419,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       limit: 500,
-      logic: ['<', '@id_1698231933579.unitPrice', '10'],
+      logic: [NumberFilterTypes.LESS_THAN, '@id_1698231933579.unitPrice', '10'],
       query: [
         {
           id: 'path_0',
@@ -447,7 +449,7 @@ describe('query2Cypher', () => {
     const query: BackendQueryFormat = {
       saveStateID: 'test',
       return: ['*'],
-      logic: ['>', ['Count', '@p1'], '1'],
+      logic: [NumberFilterTypes.GREATER_THAN, [NumberAggregationTypes.COUNT, '@p1'], '1'],
       query: [
         {
           id: 'path1',
@@ -523,7 +525,7 @@ describe('query2Cypher', () => {
           },
         },
       ],
-      logic: ['Upper', '@id_1731428699410.name'],
+      logic: [StringFunctionTypes.UPPER, '@id_1731428699410.name'],
       return: ['*'],
     };
 
@@ -618,7 +620,11 @@ describe('query2Cypher', () => {
       limit: 100,
       return: ['*'],
       cached: false,
-      logic: ['And', ['==', '@id_1737115397423.GO', '"852349"'], ['==', '@id_1737115886717.goodFlow', 'false']],
+      logic: [
+        'And',
+        [NumberFilterTypes.EQUAL, '@id_1737115397423.GO', '"852349"'],
+        [NumberFilterTypes.EQUAL, '@id_1737115886717.goodFlow', 'false'],
+      ],
     };
 
     const cypher = query2Cypher(query);
diff --git a/src/utils/reactflow/query2backend.ts b/src/utils/reactflow/query2backend.ts
index 7b797d23f1591731aebd5b0b89dbf0f3d5a86478..4625218154a816479a5cb41504ef6ca5d148c55c 100644
--- a/src/utils/reactflow/query2backend.ts
+++ b/src/utils/reactflow/query2backend.ts
@@ -2,7 +2,7 @@ import type { SerializedNode } from 'graphology-types';
 import { hasCycle } from 'graphology-dag';
 import Graph from 'graphology';
 import { allSimplePaths } from 'graphology-simple-path';
-import type { BackendQueryFormat, NodeStruct, QueryStruct, RelationStruct } from 'ts-common';
+import { AllLogicMap, type BackendQueryFormat, type NodeStruct, type QueryStruct, type RelationStruct } from 'ts-common';
 import type { MachineLearning } from 'ts-common/src/model/query/queryRequestModel';
 
 import type {
@@ -44,7 +44,7 @@ const traverseEntityRelationPaths = (
           x: node.attributes.x,
           y: node.attributes.x,
           depth: { min: settings.depth.min, max: settings.depth.max },
-          direction: 'both',
+          direction: QueryRelationDirection.BOTH,
           attributes: [],
         });
       } else {
@@ -98,9 +98,17 @@ function calculateQueryLogic(
   node: SerializedNode<LogicNodeAttributes>,
   graph: QueryMultiGraph,
   logics: SerializedNode<LogicNodeAttributes>[],
-): AllLogicStatement {
+): AllLogicStatement | undefined {
   if (!node?.attributes) throw Error('Malformed Graph! Node has no attributes');
   const connectionsToLeft = graph.edges.filter(e => e.target === node.key);
+  const connectionsToRight = graph.edges.filter(e => e.source === node.key);
+
+  const first = node.attributes.logic.logic[0];
+  const logicMap = Object.values(AllLogicMap).find(value => value.type === first);
+  if (logicMap && logicMap.excludeFromQueryIfOutputNotConnected && connectionsToRight.length === 0) {
+    log.debug('AllLogicMap with ignored output due to missing third term:', first, AllLogicMap[first], node.attributes.logic.logic);
+    return undefined; // Return a neutral value to ignore this logic
+  }
 
   const ret = [...node.attributes.logic.logic].map(l => {
     if (typeof l !== 'string') throw Error('Malformed Graph! Logic node has no logic');
@@ -159,7 +167,7 @@ function queryLogicUnion(
 ): AllLogicStatement | undefined {
   const graphLogicChunks = nodes.map(node => calculateQueryLogic(node, graph, logics));
 
-  if (graphLogicChunks.length === 0) return undefined;
+  if (graphLogicChunks.length === 0 || !graphLogicChunks[0]) return undefined;
   if (graphLogicChunks.length === 1) return graphLogicChunks[0];
 
   const constraintNodeId = nodes[0].key;