public void index(final Object primaryKey, final List foreignKeys) {
      // if the association is a unidirectional one-to-many we store the keys
      // embedded in the owning entity, otherwise we use a foreign key
      if (!association.isBidirectional()) {
        mongoTemplate.execute(
            new DbCallback<Object>() {
              public Object doInDB(DB db) throws MongoException, DataAccessException {
                List dbRefs = new ArrayList();
                for (Object foreignKey : foreignKeys) {
                  if (isReference) {
                    dbRefs.add(
                        new DBRef(
                            db, getCollectionName(association.getAssociatedEntity()), foreignKey));
                  } else {
                    dbRefs.add(foreignKey);
                  }
                }
                nativeEntry.put(association.getName(), dbRefs);

                if (primaryKey != null) {
                  final DBCollection collection =
                      db.getCollection(getCollectionName(association.getOwner()));
                  DBObject query = new BasicDBObject(MONGO_ID_FIELD, primaryKey);
                  collection.update(query, nativeEntry);
                }
                return null;
              }
            });
      }
    }
 public List query(Object primaryKey) {
   // for a unidirectional one-to-many we use the embedded keys
   if (!association.isBidirectional()) {
     final Object indexed = nativeEntry.get(association.getName());
     if (indexed instanceof Collection) {
       if (indexed instanceof List) return (List) indexed;
       return new ArrayList((Collection) indexed);
     }
     return Collections.emptyList();
   }
   // for a bidirectional one-to-many we use the foreign key to query the inverse side of the
   // association
   Association inverseSide = association.getInverseSide();
   Query query = session.createQuery(association.getAssociatedEntity().getJavaClass());
   query.eq(inverseSide.getName(), primaryKey);
   query.projections().id();
   return query.list();
 }
  private void persistAssociationsOfEntity(
      PersistentEntity pe, EntityAccess entityAccess, boolean isUpdate) {

    Object obj = entityAccess.getEntity();
    DirtyCheckable dirtyCheckable = null;
    if (obj instanceof DirtyCheckable) {
      dirtyCheckable = (DirtyCheckable) obj;
    }

    for (PersistentProperty pp : pe.getAssociations()) {
      if ((!isUpdate) || ((dirtyCheckable != null) && dirtyCheckable.hasChanged(pp.getName()))) {

        Object propertyValue = entityAccess.getProperty(pp.getName());

        if ((pp instanceof OneToMany) || (pp instanceof ManyToMany)) {
          Association association = (Association) pp;

          if (propertyValue != null) {

            if (association.isBidirectional()) { // Populate other side of bidi
              for (Object associatedObject : (Iterable) propertyValue) {
                EntityAccess assocEntityAccess =
                    createEntityAccess(association.getAssociatedEntity(), associatedObject);
                assocEntityAccess.setProperty(association.getReferencedPropertyName(), obj);
              }
            }

            Iterable targets = (Iterable) propertyValue;
            persistEntities(association.getAssociatedEntity(), targets);

            boolean reversed = RelationshipUtils.useReversedMappingFor(association);

            if (!reversed) {
              if (!(propertyValue instanceof LazyEnititySet)) {
                LazyEnititySet les =
                    new LazyEnititySet(
                        entityAccess,
                        association,
                        getMappingContext().getProxyFactory(),
                        getSession());
                les.addAll(targets);
                entityAccess.setProperty(association.getName(), les);
              }
            }
          }
        } else if (pp instanceof ToOne) {
          if (propertyValue != null) {
            ToOne to = (ToOne) pp;

            if (to.isBidirectional()) { // Populate other side of bidi
              EntityAccess assocEntityAccess =
                  createEntityAccess(to.getAssociatedEntity(), propertyValue);
              if (to instanceof OneToOne) {
                assocEntityAccess.setProperty(to.getReferencedPropertyName(), obj);
              } else {
                Collection collection =
                    (Collection) assocEntityAccess.getProperty(to.getReferencedPropertyName());
                if (collection == null) {
                  collection = new ArrayList();
                  assocEntityAccess.setProperty(to.getReferencedPropertyName(), collection);
                }
                if (!collection.contains(obj)) {
                  collection.add(obj);
                }
              }
            }

            persistEntity(to.getAssociatedEntity(), propertyValue);

            boolean reversed = RelationshipUtils.useReversedMappingFor(to);
            String relType = RelationshipUtils.relationshipTypeUsedFor(to);

            if (!reversed) {
              getSession()
                  .addPendingInsert(
                      new RelationshipPendingInsert(
                          entityAccess,
                          relType,
                          new EntityAccess(to.getAssociatedEntity(), propertyValue),
                          getCypherEngine()));
            }
          }
        } else {
          throw new IllegalArgumentException(
              "wtf don't know how to handle " + pp + "(" + pp.getClass() + ")");
        }
      }
    }
  }