Короче говоря, я работаю внутри гигантской неприятной рекурсивной функции, которая создает объект mongo Document. Мне нужно расширить функциональные возможности этой функции для поддержки сложных запросов, и мне нужно знать, как создать прямую копию (а не ссылку на объект) объекта документа mongo. Есть ли способ сделать это? Текущая реализация делает следующее:
private Document generateArrayAddsDoc(DataChanges dataChanges, Document filter)
{
Document arrayUpdatesDoc = new Document();
generateArrayDocImpl(arrayUpdatesDoc, null, dataChanges, DataChanges.Type.MODEL_ADD, filter, 0);
return arrayUpdatesDoc;
}
Вот неприятная рекурсивная функция только для контекста:
private void generateArrayDocImpl(Document arrayUpdateDoc, String parentFieldName, DataChanges dataChanges, DataChanges.Type type, Document filter, int currentLevel)
{
switch (dataChanges.getType())
{
case MODEL_UPDATE:
{
for (DataChange dataChange : dataChanges.getDataChanges())
{
if (dataChange.getNewValue() instanceof DataChanges)
{
DataChanges arrayChanges = (DataChanges) dataChange.getNewValue();
Document arrayDoc = new Document();
String dotFieldName = generateDotFieldName(parentFieldName, dataChange.getFieldName());
if (type == DataChanges.Type.MODEL_ADD || type == DataChanges.Type.MODEL_DELETE)
{
generateArrayDocImpl(arrayDoc, dotFieldName, arrayChanges, type, filter, currentLevel+1);
}
if (!arrayDoc.isEmpty())
{
if (currentLevel > 0)
{
arrayUpdateDoc.append(dotFieldName, arrayDoc);
}
else
{
arrayUpdateDoc = arrayDoc; // need to direct copy instead of referencing here
}
}
}
}
break;
}
case ARRAY_UPDATE:
{
List<Document> updateDocsList = new ArrayList<>();
for (DataChange dataChange : dataChanges.getDataChanges())
{
Document arrayElementDoc = null;
DataChanges arrayElementChanges = (DataChanges) dataChange.getNewValue();
if (arrayElementChanges.getType() == type)
{
arrayElementDoc = generateFieldUpdatesDoc(arrayElementChanges, filter);
}
else if (arrayElementChanges.getType() == DataChanges.Type.MODEL_UPDATE)
{
String dotFieldName = generateDollarSignIndexedFieldName(parentFieldName, dataChange.getFieldName());
generateArrayDocImpl(arrayUpdateDoc, dotFieldName, arrayElementChanges, type, filter, currentLevel+1);
}
if (null != arrayElementDoc && !arrayElementDoc.isEmpty())
{
updateDocsList.add(arrayElementDoc);
}
}
if (!updateDocsList.isEmpty() && type == DataChanges.Type.MODEL_ADD)
{
arrayUpdateDoc.append("$each", updateDocsList);
}
if (!updateDocsList.isEmpty() && type == DataChanges.Type.MODEL_DELETE)
{
String fieldName = pullFieldNameFromList(updateDocsList);
List<String> valuesToDelete = getValuesToDelete(updateDocsList);
Document doc = new Document();
doc.append("$in", valuesToDelete);
arrayUpdateDoc.append(fieldName, doc);
}
break;
}
}
}
Если эта функция выполняет «arrayUpdateDoc = arrayDoc;», мне нужно скопировать документ в новый объект, потому что arrayDoc уничтожается после завершения вызова этой функции, что приводит к ошибке. Будем очень признательны за любые рекомендации по выполнению прямой копии объекта (не по ссылке) объекта mongo Document!

Вы можете получить карту ввода документов и передать ее конструктору при создании нового документа:
Document original = someDocument;
Document clone = new Document(original.entrySet());
В твоем случае:
arrayUpdateDoc = new Document(arrayDoc.entrySet());
//Редактировать:
Я ошибся.
Однако Document реализует Map<String, Object>.
Это означает, что следующее должно работать:
arrayUpdateDoc = new Document(arrayDoc);
// Другое редактирование:
То, что вы пытаетесь сделать, не будет работать на Java. например:
public static void main(String[] args)
{
String test = "test";
System.out.println(test);
someMethod(test);
System.out.println(test);
}
public static void someMethod(String test)
{
test = "changed";
}
вывод:
test
test
Ссылка на вызывающий абонент не будет обновлена для нового объекта. Ссылка копируется при вызове метода. Итак, насколько я знаю, вам понадобится возвращаемый тип для вашего метода.
Это все еще не работает. Я могу заставить эту функцию работать должным образом, заставив ее возвращать новый объект в соответствии с вашим предложением, но, похоже, она все еще использует ссылку на старый объект, когда я заменяю документ, передаваемый в качестве аргумента, на вновь созданный.
Я хотел бы, чтобы реализация согласовывалась с тем, что уже существует, сохраняя ее как функцию void и просто обновляя объект Document, который передается в
это не работает, поскольку конструктор Document (Set <String>, Set <Map.Entry <String, Object >>) не определен