Index: src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java	(revision 1412906)
+++ src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java	(working copy)
@@ -19,6 +19,7 @@
 import java.util.Arrays;
 
 import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.IndexHook;
 import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
@@ -27,6 +28,7 @@
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 public class PropertyIndexTest {
 
@@ -134,5 +136,100 @@
         // assertTrue(withoutIndex > withIndex);
     }
 
+    @Test
+    public void testUnique() throws Exception {
+
+        NodeState root = MemoryNodeState.EMPTY_NODE;
+
+        // Add index definition
+        NodeBuilder builder = root.builder();
+        builder.child("oak:index").child("fooIndex")
+                .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME)
+                .setProperty("type", "property")
+                .setProperty("unique", "true")
+                .setProperty("propertyNames", Arrays.asList("foo"), Type.STRINGS);
+
+        NodeState before = builder.getNodeState();
+        builder = before.builder();
+        builder.child("a").setProperty("foo", "abc");
+        builder.child("b").setProperty("foo", Arrays.asList("abc", "def"),
+                Type.STRINGS);
+        NodeState after = builder.getNodeState();
+
+        IndexHook p = new PropertyIndexDiff(builder);
+        after.compareAgainstBaseState(before, p);
+        try {
+            p.apply();
+            fail("Unique constraint should be respected");
+        } catch (CommitFailedException e) {
+            // expected
+        } finally {
+            p.close();
+        }
+    }
+
+    @Test
+    public void testUniqueByTypeOK() throws Exception {
+
+        NodeState root = MemoryNodeState.EMPTY_NODE;
+
+        // Add index definition
+        NodeBuilder builder = root.builder();
+        builder.child("oak:index").child("fooIndex")
+                .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME)
+                .setProperty("type", "property")
+                .setProperty("unique", "true")
+                .setProperty("propertyNames", Arrays.asList("foo"), Type.STRINGS)
+                .setProperty(PropertyIndexDiff.declaringNodeTypes, Arrays.asList("typeFoo"), Type.STRINGS);
+        NodeState before = builder.getNodeState();
+        builder = before.builder();
+        builder.child("a")
+                .setProperty("jcr:primaryType", "typeFoo", Type.NAME)
+                .setProperty("foo", "abc");
+        builder.child("b")
+                .setProperty("jcr:primaryType", "typeBar", Type.NAME)
+                .setProperty("foo", "abc");
+        NodeState after = builder.getNodeState();
+
+        IndexHook p = new PropertyIndexDiff(builder);
+        after.compareAgainstBaseState(before, p);
+        p.apply();
+        p.close();
+    }
+
+    @Test
+    public void testUniqueByTypeKO() throws Exception {
+
+        NodeState root = MemoryNodeState.EMPTY_NODE;
+
+        // Add index definition
+        NodeBuilder builder = root.builder();
+        builder.child("oak:index").child("fooIndex")
+                .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME)
+                .setProperty("type", "property")
+                .setProperty("unique", "true")
+                .setProperty("propertyNames", Arrays.asList("foo"), Type.STRINGS)
+                .setProperty(PropertyIndexDiff.declaringNodeTypes, Arrays.asList("typeFoo"), Type.STRINGS);
+        NodeState before = builder.getNodeState();
+        builder = before.builder();
+        builder.child("a")
+                .setProperty("jcr:primaryType", "typeFoo", Type.NAME)
+                .setProperty("foo", "abc");
+        builder.child("b")
+                .setProperty("jcr:primaryType", "typeFoo", Type.NAME)
+                .setProperty("foo", "abc");
+        NodeState after = builder.getNodeState();
+
+        IndexHook p = new PropertyIndexDiff(builder);
+        after.compareAgainstBaseState(before, p);
+        try {
+            p.apply();
+            fail("Unique constraint should be respected");
+        } catch (CommitFailedException e) {
+            // expected
+        } finally {
+            p.close();
+        }
+    }
 
 }
Index: src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexUpdate.java
===================================================================
--- src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexUpdate.java	(revision 1412906)
+++ src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexUpdate.java	(working copy)
@@ -40,6 +40,8 @@
  * <p>
  * The changes are temporarily added to an in-memory structure, and then applied
  * to the node.
+ * </p>
+ * 
  */
 class PropertyIndexUpdate {
 
@@ -49,6 +51,13 @@
     private final String path;
 
     /**
+     * The node types that this index applies to. If <code>null</code> or
+     * <code>empty</code> then the node type of the indexed node is ignored
+     * 
+     */
+    private final List<String> nodeTypeNames;
+
+    /**
      * The node where the index definition is stored.
      */
     private final NodeBuilder node;
@@ -68,7 +77,12 @@
     private final Map<String, Set<String>> remove;
 
     public PropertyIndexUpdate(String path, NodeBuilder node) {
+        this(path, node, null);
+    }
+
+    public PropertyIndexUpdate(String path, NodeBuilder node, List<String> nodeTypeNames) {
         this.path = path;
+        this.nodeTypeNames = nodeTypeNames;
         this.node = node;
         this.insert = Maps.newHashMap();
         this.remove = Maps.newHashMap();
@@ -175,4 +189,7 @@
         }
     }
 
+    public List<String> getNodeTypeNames() {
+        return nodeTypeNames;
+    }
 }
Index: src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
===================================================================
--- src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java	(revision 1412906)
+++ src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java	(working copy)
@@ -40,7 +40,7 @@
  * <p>
  * To define a property index on a subtree you have to add an <code>oak:index</code> node.
  * 
- * Under it follows the index definition node that:
+ * Next (as a child node) follows the index definition node that:
  * <ul>
  * <li>must be of type <code>oak:queryIndexDefinition</code></li>
  * <li>must have the <code>type</code> property set to <b><code>property</code></b></li>
@@ -48,8 +48,11 @@
  * </ul>
  * </p>
  * <p>
- * Optionally you can specify the uniqueness constraint on a property index by
- * setting the <code>unique</code> flag to <code>true</code>.
+ * Optionally you can specify
+ * <ul> 
+ * <li> that the property index only applies to a certain node type by setting the <code>declaringNodeTypes</code> property</li>
+ * <li> a uniqueness constraint on a property index by setting the <code>unique</code> flag to <code>true</code></li>
+ * </ul>
  * </p>
  * 
  * <p>
@@ -68,6 +71,7 @@
  *         .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME)
  *         .setProperty("type", "property")
  *         .setProperty("propertyNames", "jcr:uuid")
+ *         .setProperty("declaringNodeTypes", "mix:referenceable")
  *         .setProperty("unique", true)
  *         .setProperty("reindex", true);
  * }
Index: src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDiff.java
===================================================================
--- src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDiff.java	(revision 1412906)
+++ src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDiff.java	(working copy)
@@ -22,14 +22,15 @@
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NODE_TYPE;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.property.PropertyIndex.TYPE;
+import static com.google.common.collect.Lists.newArrayList;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
@@ -52,6 +53,10 @@
  */
 class PropertyIndexDiff implements IndexHook {
 
+    protected static String propertyNames = "propertyNames";
+
+    protected static String declaringNodeTypes = "declaringNodeTypes";
+
     /**
      * The parent (null if this is the root node).
      */
@@ -134,21 +139,44 @@
      */
     private Iterable<PropertyIndexUpdate> getIndexes(String name) {
         List<PropertyIndexUpdate> indexes = updates.get(name);
-        if (indexes != null) {
-            return indexes;
-        } else {
+        if (indexes == null) {
             return ImmutableList.of();
         }
+        List<PropertyIndexUpdate> filtered = new ArrayList<PropertyIndexUpdate>();
+        for (PropertyIndexUpdate pi : indexes) {
+            if (pi.getNodeTypeNames() == null
+                    || pi.getNodeTypeNames().isEmpty()) {
+                filtered.add(pi);
+                continue;
+            }
+            PropertyState ps = node.getProperty(JCR_PRIMARYTYPE);
+            String type = ps != null && !ps.isArray() ? ps
+                    .getValue(Type.STRING) : null;
+            if (type != null) {
+                for (String typeName : pi.getNodeTypeNames()) {
+                    if (typeName.equals(type)) {
+                        filtered.add(pi);
+                        break;
+                    }
+                }
+            }
+        }
+        return filtered;
     }
 
     private void update(NodeBuilder builder, String indexName) {
-        PropertyState ps = builder.getProperty("propertyNames");
+        List<String> typeNames = ImmutableList.of();
+        PropertyState appliesTo = builder.getProperty(declaringNodeTypes);
+        if (appliesTo != null) {
+            typeNames = newArrayList(appliesTo.getValue(Type.STRINGS));
+        }
+        PropertyState ps = builder.getProperty(propertyNames);
         Iterable<String> propertyNames = ps != null ? ps.getValue(Type.STRINGS)
                 : ImmutableList.of(indexName);
         for (String pname : propertyNames) {
             List<PropertyIndexUpdate> list = this.updates.get(pname);
             if (list == null) {
-                list = Lists.newArrayList();
+                list = newArrayList();
                 this.updates.put(pname, list);
             }
             boolean exists = false;
@@ -159,7 +187,7 @@
                 }
             }
             if (!exists) {
-                list.add(new PropertyIndexUpdate(getPath(), builder));
+                list.add(new PropertyIndexUpdate(getPath(), builder, typeNames));
             }
         }
     }
