Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
 Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
Подключил к своему проекту MongoDB (Mongo Cloud) и складываю туда объекты в виде документов.

Репозиторий для общения с БД:
@Repository
public interface GooglePlayGamesRepository extends MongoRepository <GooglePlayGame, String> {

    GooglePlayGame findByTitleIgnoreCase(String gameTitle);

    @Aggregation("{$sample: {size: ?0} }")
    List<GooglePlayGame> findRandomGames(Long amount);

    List<GooglePlayGame> findByTitleContainsIgnoreCase(String gameTitle);

}

Сам объект, который сохраняю:
import org.springframework.data.annotation.Id;

@Document(collection = "googleplaygames")
@Getter
@Component
public final class GooglePlayGame implements Serializable {

    @Id
    String title; //это уникальный ключ!
    String genre;
    String price;
...
}


Если сохранять объект в таком виде, в коллекции MongoDB поле title заменяется на _id, а title просто становится null и никак не отображается в коллекции, так как если пробую добавить ещё одну игру, вылетает exception:
org.springframework.dao.DuplicateKeyException: E11000 duplicate key error collection: 5ef31a21233f9c398f473c6e_botapi.googleplaygames index: title dup key: { title: null };

Если убрать аннотацию @Id, то в коллекции будут храниться дубликаты и будет две одинаковых игры, у которых отличается поле "номер версии". Мне игра нужна в единственном экземпляре: если у игры, например, изменился номер версии, я хочу перезаписать этот объект (если он уже есть в БД) с новой версией.

Пробовал с помощью аннотации @Indexed(unique = true) на поле. В таком случае другие игры добавляются, но если я пробую перезаписать старый объект с таким же полем, то также получаю DuplicateKey.

Для сохранения в БД использую метод save.

Как быть? Писать ручками запрос?
28 июн 20, 15:58    [22158601]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5388
miroooha,

https://www.google.com/search?newwindow=1&client=tablet-android-huawei&ei=NHD5Xs3kBcHIrgTTwYDgDw&q=mongo cloud id primary key&oq=Mongo Cloud id primary&gs_lcp=ChNtb2JpbGUtZ3dzLXdpei1zZXJwEAEYADIFCCEQoAE6BAgAEEc6BAgAEAo6AggAOggIABAWEAoQHjoICCEQFhAdEB46BQgAEM0COgcIIRAKEKABUJ8xWM6zAWD9wgFoA3ABeACAAaIKiAHFJpIBDzAuMi41LjIuMC4xLjEuMZgBAKABAQ&sclient=mobile-gws-wiz-serp
?
29 июн 20, 07:39    [22158777]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
PetroNotC Sharp
miroooha,

https://www.google.com/search?newwindow=1&client=tablet-android-huawei&ei=NHD5Xs3kBcHIrgTTwYDgDw&q=mongo cloud id primary key&oq=Mongo Cloud id primary&gs_lcp=ChNtb2JpbGUtZ3dzLXdpei1zZXJwEAEYADIFCCEQoAE6BAgAEEc6BAgAEAo6AggAOggIABAWEAoQHjoICCEQFhAdEB46BQgAEM0COgcIIRAKEKABUJ8xWM6zAWD9wgFoA3ABeACAAaIKiAHFJpIBDzAuMi41LjIuMC4xLjEuMZgBAKABAQ&sclient=mobile-gws-wiz-serp
?

Primary Key - это и есть аннотация @Id у меня в примере. И с ней не работает. Он смотрит, что я добавляю объект с таким же полем и тут же DuplicationError, не смотря на то, что другие поля уже отличаются.
29 июн 20, 12:31    [22158981]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
В доках написано, что метод save работает как insert, если такого документа нет, и как update, если документ уже есть. Но кто-то меня обманывает, либо что-то недоговаривает. Никакого update у меня не происходит.

Сообщение было отредактировано: 29 июн 20, 12:32
29 июн 20, 12:32    [22158985]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5388
miroooha,
Значит ссылку где обманывают сюда. И код тоже сюда.
29 июн 20, 12:58    [22159006]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5388
miroooha,
Там в веб в примере id строковый тип?
29 июн 20, 13:02    [22159008]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
PetroNotC Sharp
miroooha,
Значит ссылку где обманывают сюда. И код тоже сюда.

https://www.concretepage.com/spring-5/spring-data-mongorepository-update#save

В подобных примерах в основном числовой тип, а не строковый. У меня же строка.

Да и этот метод save() наследуется от CrudRepository. И опять же, пишут, что он работает и как update, например тут:
https://www.baeldung.com/spring-data-crud-repository-save

Сообщение было отредактировано: 29 июн 20, 13:19
29 июн 20, 13:20    [22159016]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5388
miroooha,

>В подобных примерах в основном числовой тип, а не строковый. У меня же строка.
Вот и сделай числовой. И потом с примером сюда.
29 июн 20, 14:11    [22159064]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
PetroNotC Sharp
miroooha,

>В подобных примерах в основном числовой тип, а не строковый. У меня же строка.
Вот и сделай числовой. И потом с примером сюда.

А нафига мне числовой то? Если у меня поиск по названию игры. На кой черт мне вообще это число? :D Ввести доп.переменную числового типа и пометить её как primary key? Я попробую, но выглядит абсурдно.
29 июн 20, 21:02    [22159255]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 17915
miroooha
А нафига мне числовой то? Если у меня поиск по названию игры. На кой черт мне вообще это число? :D Ввести доп.переменную числового типа и пометить её как primary key? Я попробую, но выглядит абсурдно
вообще-то это первое дело в таблицах иметь поде id primary key
29 июн 20, 22:16    [22159280]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 17915
miroooha
А нафига мне числовой то? Если у меня поиск по названию игры. На кой черт мне вообще это число? :D Ввести доп.переменную числового типа и пометить её как primary key? Я попробую, но выглядит абсурдно
вообще-то это первое дело в таблицах иметь поде id primary key
29 июн 20, 22:16    [22159281]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
вадя
miroooha
А нафига мне числовой то? Если у меня поиск по названию игры. На кой черт мне вообще это число? :D Ввести доп.переменную числового типа и пометить её как primary key? Я попробую, но выглядит абсурдно
вообще-то это первое дело в таблицах иметь поде id primary key

Оно обязательно должно быть числом? У меня есть primary key, который весит на стринге. Мне предлагают снять этот primary key с этой стринги, ввести доп.поле числового типа и повесить на него pk.

Ну я буду пробовать, потом отпишусь о результатах.

Сообщение было отредактировано: 29 июн 20, 22:31
29 июн 20, 22:29    [22159289]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 17915
miroooha
Оно обязательно должно быть числом?
если ты хочешь иметь тормоза - то можешь что угодно использовать.
кроме этого поле primary key делают автоинкриментным
30 июн 20, 07:24    [22159394]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5388
miroooha,
Долго пробуешь.
Заработает, поставишь строковое. Делов то.
30 июн 20, 07:42    [22159399]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
mayton
Member

Откуда: loopback
Сообщений: 47981
Обычно title не выбирают на роль уникального ключа. По смыслу - он больше атрибут. Или комментарий.
30 июн 20, 08:33    [22159420]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
вадя
miroooha
Оно обязательно должно быть числом?
если ты хочешь иметь тормоза - то можешь что угодно использовать.
кроме этого поле primary key делают автоинкриментным

Ну это понятно, что сравнить два числа гораздо быстрее, чем строку.

Попробовал так:
Вручную ввел доп.поле типа ObjectId, которое генерит сама монго, если не видит аннотации @Id. Повесил на неё @Id, а на название повесил индекс на уникальность. Проверил: взял объект из БД, через сеттер изменил одно из полей и попробовал сохранить измененный объект - всё прошло успешно.
import org.bson.types.ObjectId;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;

...

@Id
ObjectId id;
@Indexed(unique = true)
String title;


Окей, объект изменился, никаких дубликат error.

Однако, дальше через свой парсер снова пытаюсь сохранить объект (у которого это измененное поле уже другое) - и снова ничего не работает! Чудеса да и только.

Если брать объект из БД, менять через сеттер ему поле, и сохранять обратно - то всё работает. А как только пытаюсь сохранить готовый объект (у которого новое значение в поле) - так снова DuplicateKey.
30 июн 20, 13:48    [22159654]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5388
miroooha,
Второй нерабочий случай не понял.
Транзакция должна быть короткой 0,1сек.
С коммитом.
Поле id менять нельзя.
30 июн 20, 13:52    [22159658]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
PetroNotC Sharp
miroooha,
Второй нерабочий случай не понял.
Транзакция должна быть короткой 0,1сек.
С коммитом.
Поле id менять нельзя.

Ну в первом случае я взял объект с игрой из БД, сохранил его в локальную переменную, через сеттер изменил значение одного поля и тут же через метод save() сохранил в БД. В результате у этого объекта в БД изменилось соответствующее поле - т.е. то, чего я и добивался.

Про второй случай. У меня же есть парсер, который по ссылке достаёт всю информацию об игре, которую я потом сохраняю в БД. Я знаю, что у меня в БД сейчас лежит объект, у которого тот же самый title, что и у игры, которую я парсю. Но одно поле у объекта, который лежит в БД и объекта, который я получил в ходе парсинга - разные.
Т.е. по идее всё должно сработать как и в первом сценарии - перезаписаться одно поле. Но здесь получаю DuplicateKey.

P.S. Т.е. если я в будущем захочу обновить игру в БД по одной ссылке и 1 запросу с парсера, если у неё условно сменится номер, или цена, то я получу ошибку.

Сообщение было отредактировано: 30 июн 20, 13:59
30 июн 20, 13:59    [22159665]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
Грубо говоря, он не хочет просто взять и "переписать" старый объект на новый, у которого новые значения. Надо взять уже имеющийся объект и БД, изменить ему поля и закинуть его обратно. Не очень удобно для моего сценария.

Особенности NoSQL? Mongo? Или моих кривых рук? С Postgres всё работало по описанному сценарию.

Я уже понимаю, что похоже загвоздка в id, так как при парсинге создаётся новый объект. Он видит, что у объектов разные id, но одинаковые поля title и не пускает. Но как её решить..

Сообщение было отредактировано: 30 июн 20, 14:08
30 июн 20, 14:03    [22159669]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
При каждом запросе залезать в БД и проверять, есть ли там такая игра. Если есть, то достать и сравнить с той, что выдал парсер. Прогнать и сравнить через equals, и в случае несовпадения заменить через сеттер соответствующие поля и обновить объект в БД. Как-то не комильфо.

Сообщение было отредактировано: 30 июн 20, 14:14
30 июн 20, 14:14    [22159682]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
miroooha
При каждом запросе залезать в БД и проверять, есть ли там такая игра. Если есть, то достать и сравнить с той, что выдал парсер. Прогнать и сравнить через equals, и в случае несовпадения заменить через сеттер соответствующие поля и обновить объект в БД. Как-то не комильфо.

Ещё один костыль, который только что испробовал: при попытке сохранить объект в БД ловить этот exception на дубликат. В catch блоке во временную переменную складывать объект из БД с таким же названием. Доставать у него этот уникальный id, и через сеттер ставить тому объекту, который пытаюсь сохранить. В результате объект в БД обновляется. Но как-то мне не очень нравится такой вариант (но хоть работает) :D
30 июн 20, 14:29    [22159697]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 8775
Посмотреть, чем "объект из БД" отличается от того, что ты пытаешься пихать, не судьба?
30 июн 20, 14:52    [22159706]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
miroooha
Member

Откуда:
Сообщений: 65
Leonid Kudryavtsev
Посмотреть, чем "объект из БД" отличается от того, что ты пытаешься пихать, не судьба?

Я это только что выше в принципе и описал.
Просто завернул в catch, чтобы проверять что там нового только в том случае, если такой объект уже есть (при DuplicateKeyExсeption). Проверять каждый нет необходимости.

Просто при работе с Postgres таких проблем не было, он сам всё решал за меня. А здесь вот так вот выходит.

Сообщение было отредактировано: 30 июн 20, 14:57
30 июн 20, 14:57    [22159710]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5388
miroooha
При каждом запросе залезать в БД и проверять, есть ли там такая игра. Если есть, то достать и сравнить с той, что выдал парсер. Прогнать и сравнить через equals, и в случае несовпадения заменить через сеттер соответствующие поля и обновить объект в БД. Как-то не комильфо.

Вы много думаете.
При ОРМ не надо жалеть комп и много думать.
Именно так!
Читаем ПОСЛЕДНЮЮ версию объекта и меняем за 0, 00001 сек.
30 июн 20, 15:39    [22159747]     Ответить | Цитировать Сообщить модератору
 Re: Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5388
miroooha,
Я не понял что за парсер такой?
Все работы с бд должны быть через одни ворота. Например hibernate.
Если jdbc, то аккуратно и отдельный проект.
Что за парсер?
30 июн 20, 15:42    [22159750]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
Все форумы / Java Ответить