diff --git a/frontend/src/metabase/lib/expressions/config.js b/frontend/src/metabase/lib/expressions/config.js
index d23f2dcd67bf064d88b6b40ea9d34b73b4123bdf..60d780106e9b4c8b377767bca09e63738277f2ea 100644
--- a/frontend/src/metabase/lib/expressions/config.js
+++ b/frontend/src/metabase/lib/expressions/config.js
@@ -29,6 +29,11 @@ export const EDITOR_QUOTES = {
 //   identifierAlwaysQuoted: false,
 // };
 
+export const EDITOR_FK_SYMBOLS = {
+  symbols: [".", " → "],
+  default: " → ",
+};
+
 // copied relevant parts from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
 export const OPERATOR_PRECEDENCE = {
   not: 17,
diff --git a/frontend/src/metabase/lib/expressions/index.js b/frontend/src/metabase/lib/expressions/index.js
index 0b06efe8cdb8bccbec4374fbb322c920b652a8b6..0bfb41725879237f0b610925fa5b3e2286fe0b1f 100644
--- a/frontend/src/metabase/lib/expressions/index.js
+++ b/frontend/src/metabase/lib/expressions/index.js
@@ -1,7 +1,14 @@
 export * from "./config";
 
 import Dimension from "metabase-lib/lib/Dimension";
-import { OPERATORS, FUNCTIONS, EDITOR_QUOTES, getMBQLName } from "./config";
+import { FK_SYMBOL } from "metabase/lib/formatting";
+import {
+  OPERATORS,
+  FUNCTIONS,
+  EDITOR_QUOTES,
+  EDITOR_FK_SYMBOLS,
+  getMBQLName,
+} from "./config";
 
 // IDENTIFIERS
 
@@ -60,15 +67,22 @@ export function parseDimension(name, { query }) {
   return query
     .dimensionOptions()
     .all()
-    .find(d => getDimensionName(d) === name);
+    .find(d =>
+      EDITOR_FK_SYMBOLS.symbols.some(
+        separator => getDimensionName(d, separator) === name,
+      ),
+    );
 }
 
 export function formatDimensionName(dimension, options) {
   return formatIdentifier(getDimensionName(dimension), options);
 }
 
-export function getDimensionName(dimension) {
-  return dimension.render();
+export function getDimensionName(
+  dimension,
+  separator = EDITOR_FK_SYMBOLS.default,
+) {
+  return dimension.render().replace(` ${FK_SYMBOL} `, separator);
 }
 
 // STRING LITERALS
diff --git a/frontend/src/metabase/lib/expressions/lexer.js b/frontend/src/metabase/lib/expressions/lexer.js
index 6e56e7976ae9b870bb5dcca90b9bd65d26f41939..40bc0fd96ba8b1ea0c3aa53ffc0b489fdfe1590a 100644
--- a/frontend/src/metabase/lib/expressions/lexer.js
+++ b/frontend/src/metabase/lib/expressions/lexer.js
@@ -37,7 +37,7 @@ function createClauseToken(name, options = {}) {
 
 export const Identifier = createToken({
   name: "Identifier",
-  pattern: /\w+/,
+  pattern: /(\w|\.)+/,
   label: "identfier",
 });
 export const IdentifierString = createToken({
diff --git a/frontend/src/metabase/lib/expressions/suggest.js b/frontend/src/metabase/lib/expressions/suggest.js
index 1c1d4c2271504f5d5ce7af530543ab6255bdd76a..5183be6b40173cccbbb1f2557e6337f011e627ae 100644
--- a/frontend/src/metabase/lib/expressions/suggest.js
+++ b/frontend/src/metabase/lib/expressions/suggest.js
@@ -52,6 +52,7 @@ import {
   isExpressionType,
   getFunctionArgType,
   EXPRESSION_TYPES,
+  EDITOR_FK_SYMBOLS,
 } from "./config";
 
 const FUNCTIONS_BY_TYPE = {};
@@ -91,13 +92,23 @@ export function suggest({
   if (
     lastInputToken &&
     ((isTokenType(lastInputToken.tokenType, Identifier) &&
-      /\w/.test(partialSource[partialSource.length - 1])) ||
+      Identifier.PATTERN.test(partialSource[partialSource.length - 1])) ||
       lastInputTokenIsUnclosedIdentifierString)
   ) {
     tokenVector = tokenVector.slice(0, -1);
     partialSuggestionMode = true;
   }
 
+  const identifierTrimOptions = lastInputTokenIsUnclosedIdentifierString
+    ? {
+        // use the last token's pattern anchored to the end of the text
+        prefixTrim: new RegExp(lastInputToken.tokenType.PATTERN.source + "$"),
+      }
+    : {
+        prefixTrim: new RegExp(Identifier.PATTERN.source + "$"),
+        postfixTrim: new RegExp("^" + Identifier.PATTERN.source + "\\s*"),
+      };
+
   const context = getContext({
     cst,
     tokenVector,
@@ -136,15 +147,6 @@ export function suggest({
         parentRule === "metricExpression" &&
         isExpressionType(expectedType, "aggregation");
 
-      const trimOptions = lastInputTokenIsUnclosedIdentifierString
-        ? {
-            // use the last token's pattern anchored to the end of the text
-            prefixTrim: new RegExp(
-              lastInputToken.tokenType.PATTERN.source + "$",
-            ),
-          }
-        : { prefixTrim: /\w+$/, postfixTrim: /^\w+\s*/ };
-
       if (isDimension) {
         let dimensions = [];
         if (
@@ -178,7 +180,10 @@ export function suggest({
             type: "fields",
             name: getDimensionName(dimension),
             text: formatDimensionName(dimension) + " ",
-            ...trimOptions,
+            alternates: EDITOR_FK_SYMBOLS.symbols.map(symbol =>
+              getDimensionName(dimension, symbol),
+            ),
+            ...identifierTrimOptions,
           })),
         );
       }
@@ -188,7 +193,7 @@ export function suggest({
             type: "segments",
             name: segment.name,
             text: formatSegmentName(segment),
-            ...trimOptions,
+            ...identifierTrimOptions,
           })),
         );
       }
@@ -198,7 +203,7 @@ export function suggest({
             type: "metrics",
             name: metric.name,
             text: formatMetricName(metric),
-            ...trimOptions,
+            ...identifierTrimOptions,
           })),
         );
       }
@@ -315,11 +320,16 @@ export function suggest({
 
   // throw away any suggestion that is not a suffix of the last partialToken.
   if (partialSuggestionMode) {
+    const input = lastInputToken.image;
     const partial = lastInputTokenIsUnclosedIdentifierString
-      ? lastInputToken.image.slice(1).toLowerCase()
-      : lastInputToken.image.toLowerCase();
+      ? input.slice(1).toLowerCase()
+      : input.toLowerCase();
     for (const suggestion of finalSuggestions) {
-      suggestion: for (const text of [suggestion.name, suggestion.text]) {
+      suggestion: for (const text of [
+        suggestion.name,
+        suggestion.text,
+        ...(suggestion.alternates || []),
+      ]) {
         const lower = (text || "").toLowerCase();
         if (lower.startsWith(partial)) {
           suggestion.range = [0, partial.length];