Hello. I inherited a project that connects to mongo using Java and morphia. I have two Java classes x and y that are persisted to mongo as the x and y collections respectively. The x and y Java classes each have a variable of type ObjectId that is annotated with @Id. Another variable, CustomerData, again in both x and y classes, is annotated with @Reference. CustomerData is also persisted in Mongo in the Customers collection. When I delete a customer (from Java using the delete() method of the Datastore class) with id “123”, documents in the x collection that have a reference to this customer are deleted (desired behavior). However, documents in collection y that have a reference to this customer are not deleted (undesired behavior). I want documents in y to also be deleted when the referenced customer is deleted. I have not been able to find any differences between x and y (in Java) that explain the difference in behavior. I believe the behavior described for x is expected because of the relationship between customer and x. I can’t explain why y does not have the same behavior. What can I look for, either in Java or some aspect of Mongo to explain why y doesn’t have the same behavior.
Morphia doesn’t support cascading deletes like that so I’m not sure why you’re seeing it in the first case. It would help to see your actual classes (names can be redacted if need be) and perhaps the code your using to delete the entities. There’s some nuance that I’m missing so far.
Thank you for the help. Here’s the code sample.
Note: the edit control for this web site can’t tell the difference between an annotation with the @ sign or a @mention and only allows for 2 mentions in a post (at least for me). Therefore, at signs are wrapped in parenthesis. Remove the () for the actual code example.
(@)Entity(“xtransactions”)
(@)Indexes({
(@)Index(“Customer, Timestamp”),
(@)Index(“Timestamp”)
})
public class XTransactionData {
(@)Id
public ObjectId Id;
(@)Reference(ignoreMissing=true)
public CustomerData Customer;
public Date Timestamp;
public byte Sample;
public byte SampleEncrypted;
public String StorageReference;
…
public void delete() throws Exception {
if (Id != null) {
Datastore ds = Support.getDatastore();
try {
// Delete the audio from cloud storage
if (!(Customer.AudioStorageMethod == null || Customer.AudioStorageMethod.equals("Local"))) {
if (StorageReference != null) {
Support.removeAudioFromCloudStorage(StorageReference, Customer, "XAudio");
}
}
// Delete the the XTransaction from the collection in Mongo
System.out.println("Before Delete");
WriteResult result = ds.delete(XTransactionData.class, Id);
System.out.println("After Delete");
System.out.println("Error: " + result.getError());
System.out.println("N: " + result.getN());
System.out.println("Last Error: " + result.getLastError());
} finally {
System.out.println("Closing X data store");
Support.closeDatastore(ds);
}
}
}
}
(@)Entity(“ytransactions”)
(@)Indexes({
(@)Index(“Customer, Timestamp”),
(@)Index(“Timestamp”)
})
public class YTransactionData {
(@)Id
public ObjectId Id;
(@)Reference(ignoreMissing=true)
public CustomerData Customer;
public Date Timestamp;
public byte[] Sample;
public byte[] SampleEncrypted;
public String StorageReference;
...
// The same functionality as XTransactionData
public void delete() throws Exception {}
}
(@)Entity(“customers”)
(@)Indexes({
(@)Index(
fields = (@)Field(value=“Name”),
options = (@)IndexOptions(unique=true)
),
(@)Index(
fields = (@)Field(value=“CalloutUsername”)
)
})
public class CustomerData {
(@)Id
public ObjectId Id;
public String Name;
public String Alias;
public String DemoAlias;
public String Description;
…
}
public DeleteCustomer(String customerid) {
DeleteXTransactionForCustomer(customerid);
DeleteYTransactionForCustomer(customerid);
DeleteUsers(customerid);
DeleteCustomerFinal(customerid);
}
// Delete the XTransaction for this customer from the X collection
// DeleteYTransactionForCustomer is identical except for the Y variant transactions
public void DeleteXTransactionForCustomer(String customerid) {
Util.LogMessage(“Deleting X transactions”);
try {
Datastore ds = Support.getDatastore();
try {
CustomerData customer = CustomerData.get(new ObjectId(customerid));
if (customer != null) {
long count;
// Create a query for the XTransactionData
Query classtransactionquery = ds.createQuery(XTransactionData.class);
// Filter on the Customer
classtransactionquery.and(classtransactionquery.criteria("Customer").equal(customer));
// Set the batch size, issue the request, and grab the iterator
Iterator<XTransactionData> classtransactionlist = classtransactionquery.batchSize(1000).fetch().iterator();
count = 0;
// Loop over all the returned records
while (classtransactionlist.hasNext()) {
XTransactionData transactiondata = classtransactionlist.next();
// Delete one at a time to ensure all blob audio is removed
transactiondata.delete();
// Increment the count
count++;
// Limit the output
if (count % 1000 == 0) {
Util.LogMessage("Deleted " + count + " X transactions so far");
}
}
// Update the output to include any additional X transactions
Util.LogMessage("Deleted " + count + " X transaction(s)");
}
} finally {
Support.closeDatastore(ds);
}
} catch (Exception ex) {
Util.LogException(ex);
}
}
public void DeleteUsers(String customerid) {
Util.LogMessage(“Deleting users”);
try {
Datastore ds = Support.getDatastore();
try {
CustomerData customer = CustomerData.get(new ObjectId(customerid));
if (customer != null) {
long count;
// Create a query for the UserData
Query userquery = ds.createQuery(UserData.class);
// Filter on the CustomerId
userquery.and(userquery.criteria("CustomerId").equal(customer));
// Set the batch size, issue the request, and grab the iterator
Iterator<UserData> userlist = userquery.batchSize(1000).fetch().iterator();
count = 0;
// Loop over all the returned records
while (userlist.hasNext()) {
UserData userdata = userlist.next();
// Delete one at a time to ensure all blob audio is removed
userdata.delete();
// Increment the count
count++;
// Limit the output
if (count % 1000 == 0) {
Util.LogMessage("Deleted " + count + " users so far");
}
}
// Update the output to include any additional X transactions
Util.LogMessage("Deleted " + count + " user(s)");
}
} finally {
Support.closeDatastore(ds);
}
} catch (Exception ex) {
Util.LogException(ex);
}
}
// Delete the customer in Mongo.
// After this is called, any remaining Y transactions now have a reference to a non-existent customer.
public void DeleteCustomerFinal(String customerid) {
try {
Datastore ds = Support.getDatastore();
try {
CustomerData customer = CustomerData.get(new ObjectId(customerid));
if (customer != null) {
Util.LogMessage(“Deleting customer”);
ds.delete(CustomerData.class, customer.Id);
} else {
Util.LogMessage(“Customer " + customerid + " could not be found”);
}
} finally {
Support.closeDatastore(ds);
}
} catch (Exception ex) {
Util.LogException(ex);
}
}