Обновить поле массива во встроенном документе mongodb с использованием Spring Data MongodB?

Я пытаюсь обновить поле массива во встроенном документе в mongodb с помощью Spring Data MongoDB.

Структура документа, который я хочу обновить / вставить в коллекцию mongodb, приведена ниже.

Подобных документов может быть больше для каждого типа отдела, например «Продажи», «Маркетинг» и так далее.

{
    "timestamp": "2014-09-26T04:00:00.000Z",
    "department": "accounts",
    "employee": [
        {
            "type": "regular",
            "names": [
                "Raj",
                "Kumar",
                "Shankar"
            ]
        },
        {
            "type": "contract",
            "names": [
                "Penny",
                "Sheldon",
                "bob"
            ]
        },
        {
            "type": "temp",
            "names": [
                "jerry",
                "kramer",
                "bubbleboy"
            ]
        }
    ]
}

В принципе, у меня есть запрос на обновление, как показано ниже,

db.getCollection('mytest').update(
   { 
        "timestamp" : "2014-09-26T04:00:00.000Z",
        "department" : "accounts",
        "employee.type" : "regular"
    },
    { $addToSet: { "employee.$.names" : "Jo" } },
    {
        upsert: true
    }
)

Я добавил upsert: true, потому что, если нет документа, соответствующего запросу, я хочу вставить документ в коллекцию mytest.

Когда я выполняю то же самое из оболочки mongo, я получаю следующую ошибку.

   The positional operator did not find the match needed from the query. Unexpanded update: employee.$.names

Даже если это сработает, я не уверен, есть ли у нас аналогичная поддержка для реализации того же в Spring Data mongodb.

Кроме того, мой другой запрос: если я хочу добавить / обновить сотрудников для нескольких отделов, скажем, «учетные записи», а также «продажи», мне кажется, что я должен выполнить один и тот же запрос с разными значениями, соответствующими количеству отделов, которое я хочу. обновить (если нет вставки) соответственно.

Есть ли лучший и эффективный вариант, такой как массовая / пакетная обработка, где я могу обновлять / вставлять сотрудников для нескольких отделов одновременно в одном запросе обновления mongo. Кроме того, есть ли поддержка в Spring data mongodb / mongotemplate для того же самого.


person juser    schedule 11.08.2016    source источник
comment
Удалось ли вам ознакомиться с приведенным ниже решением и посмотреть, решает ли оно вашу проблему?   -  person notionquest    schedule 15.08.2016


Ответы (1)


Во-первых, я должен сказать, что есть несколько сценариев, которые необходимо обработать, поскольку структура документа имеет встроенные массивы. Если возможно, попробуйте изменить структуру документа.

Краткий ответ на ошибку: - Вы получите ошибку оператора позиции, если запрос не найдет соответствующий документ.

Вот почему в приведенном ниже решении я обработал сценарий в блоке catch. Если вы можете пройти модульный тест, вы должны понять.

Решение: -

public Boolean updateDepartmentCollectionWithoutFind(String name, String timeStamp)
            throws JsonParseException, JsonMappingException, IOException {

        MongoOperations mongoOperations = getMongoConnection();

        Query query = new Query();
        query.addCriteria(Criteria.where("timestamp").is(timeStamp).and("department").is("accounts")
                .and("employee.type").is("regular"));
        Update update = new Update();
        update.addToSet("employee.$.names", name);

        try {

            System.out.println(query.toString());
            System.out.println(update.toString());

            WriteResult writeResult = mongoOperations.upsert(query, update, DepartmentCollection.class);

            if (writeResult != null) {

                System.out.println("111111111111111111 Update with position parameter has been successful :"
                        + writeResult.toString());

            }
        } catch (DataIntegrityViolationException die) {
            System.out.println("Update failed ====>" + die.getMessage());
            System.out.println("Trying to update without position parameters ...");

            Update updateWithoutPositionOperator = new Update();
            updateWithoutPositionOperator.addToSet("employee.names", name);
            WriteResult writeResultUpsert = mongoOperations.upsert(query, updateWithoutPositionOperator,
                    DepartmentCollection.class);

            if (writeResultUpsert != null) {

                System.out.println("2222222222222222222 Update without position parameter has been successful :"
                        + writeResultUpsert.toString());

            }

        }

        return true;

    }

Мой метод получения подключения для справки: - Он вам не нужен, если у вас есть контекст Spring и вы можете изменить приведенный выше код в зависимости от вашего контекста.

@SuppressWarnings("resource")
public MongoOperations getMongoConnection() {

    return (MongoOperations) new AnnotationConfigApplicationContext(SpringMongoConfig.class)
            .getBean("mongoTemplate");
}

Модульные тесты: - Я публикую модульные тесты, потому что вам нужно понимать сценарий и решение. Прочтите комментарий к каждому тесту и имени метода, чтобы понять, какой upsert выполняется для каждого сценария.

Тест 3 - это особое поведение. Пожалуйста, внимательно посмотрите на это.

@Test
    public void updateDepartmentCollectionWhenNoDocumentsPresent() throws JsonParseException, JsonMappingException, IOException {

        //Second upsert executed (i.e. without positional parameter)
        Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Raj", "2014-09-26T04:00:00.000Z"));

    }

    @Test
    public void updateDCWhenMatchingDocumentsPresentButDocumentHasOnlyRegularEmployeeType() throws JsonParseException, JsonMappingException, IOException {

        //Second upsert executed  (i.e. without positional parameter)       
        Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Jo", "2014-09-26T04:00:00.000Z"));

    }   

    @Test
    public void updateDCWhenMultipleTypesPresentButNoRegular() throws JsonParseException, JsonMappingException, IOException {

        //First upsert executed  (i.e. with positional parameter). However, it creates a new document.      
        Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Jo", "2014-09-27T04:00:00.000Z"));

    }   

    @Test
    public void updateDCWhenMultipleTypesPresentIncludingRegular() throws JsonParseException, JsonMappingException, IOException {

        //First upsert executed (i.e. with positional parameter) and existing document has been updated.        
        Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Jo", "2014-09-29T04:00:00.000Z"));

    }
person notionquest    schedule 12.08.2016