diff --git a/core/lib/Drupal/Core/Entity/Query/QueryInterface.php b/core/lib/Drupal/Core/Entity/Query/QueryInterface.php
index 630d1767396ca1c31a91615f09fca79d6adc09a2..9c05dfa4d6f231ffe73c8d14c48dc9653822c6f7 100644
--- a/core/lib/Drupal/Core/Entity/Query/QueryInterface.php
+++ b/core/lib/Drupal/Core/Entity/Query/QueryInterface.php
@@ -35,13 +35,18 @@ public function getEntityTypeId();
    *
    * @param $field
    *   Name of the field being queried. It must contain a field name, optionally
-   *   followed by a column name. The column can be "entity" for reference
-   *   fields and that can be followed similarly by a field name and so on. Some
-   *   examples:
+   *   followed by a column name. The column can be the reference property,
+   *   usually "entity", for reference fields and that can be followed
+   *   similarly by a field name and so on. Additionally, the target entity type
+   *   can be specified by appending the ":target_entity_type_id" to "entity".
+   *   Some examples:
    *   - nid
    *   - tags.value
    *   - tags
+   *   - tags.entity.name
+   *   - tags.entity:taxonomy_term.name
    *   - uid.entity.name
+   *   - uid.entity:user.name
    *   "tags" "is the same as "tags.value" as value is the default column.
    *   If two or more conditions have the same field names they apply to the
    *   same delta within that field. In order to limit the condition to a
diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
index 09cea061bddbb6c48470b227abfc30a7b31c0294..e813cde38592f12d1d5883c013ff925ab5bb7ae3 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
@@ -7,6 +7,8 @@
 use Drupal\Core\Entity\Query\QueryException;
 use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
 use Drupal\Core\Entity\Sql\TableMappingInterface;
+use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface;
+use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
 
 /**
  * Adds tables and fields to the SQL entity query.
@@ -254,10 +256,20 @@ public function addField($field, $type, $langcode) {
           $relationship_specifier = $specifiers[$key + 1];
           $next_index_prefix = $relationship_specifier;
         }
+        $entity_type_id = NULL;
+        // Relationship specifier can also contain the entity type ID, i.e.
+        // entity:node, entity:user or entity:taxonomy.
+        if (strpos($relationship_specifier, ':') !== FALSE) {
+          list($relationship_specifier, $entity_type_id) = explode(':', $relationship_specifier, 2);
+        }
         // Check for a valid relationship.
-        if (isset($propertyDefinitions[$relationship_specifier]) && $field_storage->getPropertyDefinition('entity')->getDataType() == 'entity_reference' ) {
-          // If it is, use the entity type.
-          $entity_type_id = $propertyDefinitions[$relationship_specifier]->getTargetDefinition()->getEntityTypeId();
+        if (isset($propertyDefinitions[$relationship_specifier]) && $propertyDefinitions[$relationship_specifier] instanceof DataReferenceDefinitionInterface) {
+          // If it is, use the entity type if specified already, otherwise use
+          // the definition.
+          $target_definition = $propertyDefinitions[$relationship_specifier]->getTargetDefinition();
+          if (!$entity_type_id && $target_definition instanceof EntityDataDefinitionInterface) {
+            $entity_type_id = $target_definition->getEntityTypeId();
+          }
           $entity_type = $this->entityManager->getDefinition($entity_type_id);
           $field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
           // Add the new entity base table using the table and sql column.
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryRelationshipTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryRelationshipTest.php
index 8465438207069e92e0f67468e47f032f12515a63..60dc13c67b59298676d2fa1a729160a77943b4f9 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryRelationshipTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryRelationshipTest.php
@@ -1,6 +1,8 @@
 <?php
 
 namespace Drupal\KernelTests\Core\Entity;
+
+use Drupal\Component\Plugin\Exception\PluginNotFoundException;
 use Drupal\Component\Utility\Unicode;
 use Drupal\entity_test\Entity\EntityTest;
 use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
@@ -115,7 +117,7 @@ protected function setUp() {
    * Tests querying.
    */
   public function testQuery() {
-    // This returns the 0th entity as that's only one pointing to the 0th
+    // This returns the 0th entity as that's the only one pointing to the 0th
     // account.
     $this->queryResults = $this->factory->get('entity_test')
       ->condition("user_id.entity.name", $this->accounts[0]->getUsername())
@@ -154,6 +156,56 @@ public function testQuery() {
       ->condition("$this->fieldName.entity.name", $this->terms[0]->name->value, '<>')
       ->execute();
     $this->assertResults(array(1, 2));
+    // This returns the 0th entity as that's only one pointing to the 0th
+    // account.
+    $this->queryResults = $this->factory->get('entity_test')
+      ->condition("user_id.entity:user.name", $this->accounts[0]->getUsername())
+      ->execute();
+    $this->assertResults(array(0));
+    // This returns the 1st and 2nd entity as those point to the 1st account.
+    $this->queryResults = $this->factory->get('entity_test')
+      ->condition("user_id.entity:user.name", $this->accounts[0]->getUsername(), '<>')
+      ->execute();
+    $this->assertResults(array(1, 2));
+    // This returns all three entities because all of them point to an
+    // account.
+    $this->queryResults = $this->factory->get('entity_test')
+      ->exists("user_id.entity:user.name")
+      ->execute();
+    $this->assertResults(array(0, 1, 2));
+    // This returns no entities because all of them point to an account.
+    $this->queryResults = $this->factory->get('entity_test')
+      ->notExists("user_id.entity:user.name")
+      ->execute();
+    $this->assertEqual(count($this->queryResults), 0);
+    // This returns the 0th entity as that's only one pointing to the 0th
+    // term (test without specifying the field column).
+    $this->queryResults = $this->factory->get('entity_test')
+      ->condition("$this->fieldName.entity:taxonomy_term.name", $this->terms[0]->name->value)
+      ->execute();
+    $this->assertResults(array(0));
+    // This returns the 0th entity as that's only one pointing to the 0th
+    // term (test with specifying the column name).
+    $this->queryResults = $this->factory->get('entity_test')
+      ->condition("$this->fieldName.target_id.entity:taxonomy_term.name", $this->terms[0]->name->value)
+      ->execute();
+    $this->assertResults(array(0));
+    // This returns the 1st and 2nd entity as those point to the 1st term.
+    $this->queryResults = $this->factory->get('entity_test')
+      ->condition("$this->fieldName.entity:taxonomy_term.name", $this->terms[0]->name->value, '<>')
+      ->execute();
+    $this->assertResults(array(1, 2));
+  }
+
+  /**
+   * Tests the invalid specifier in the query relationship.
+   */
+  public function testInvalidSpecifier() {
+    $this->setExpectedException(PluginNotFoundException::class);
+    $this->factory
+      ->get('taxonomy_term')
+      ->condition('langcode.language.foo', 'bar')
+      ->execute();
   }
 
   /**