powered by simpleCommunicator - 2.0.30     © 2024 Programmizd 02
Map
Форумы / Java [игнор отключен] [закрыт для гостей] / Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
25 сообщений из 78, страница 2 из 4
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974638
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PetroNotC Sharp,
Если за 0,0001 сек встретились 3 кода сохранения то этот случай надо читать в доках. В хибере настраивается перетирать старое или вызвать райзе или...
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974686
miroooha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PetroNotC Sharp
miroooha,
Я не понял что за парсер такой?
Все работы с бд должны быть через одни ворота. Например hibernate.
Если jdbc, то аккуратно и отдельный проект.
Что за парсер?

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

И вот возникает такая ситуация, что игра может быть уже в библиотеке (со старыми данными), и приходит запрос по ссылке (через парсер), и пытается сохранить (обновить) эту новую информацию в БД. Здесь у меня и был конфликт.
Вот и приходится теперь сверять объекты. Точнее я теперь при возникновении этого исключения достаю из БД игру с таким же названием, беру у него этот уникальный id, через сеттер назначаю этот же самый айди объекту с новой информацией и отправляю в БД.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974705
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miroooha,

ОК. Все верно
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974708
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miroooha, а покажи туловище парсера. Что у тебя там? JSoup? HtmlCleaner?
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974730
dakeiras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MongoDB не нужно использовать практически никогда. Это всё от нежелания учить SQL.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974776
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Возможно суммарная стоимость владения Монгой (если покупать ее как сервис у Амазона или Ажура)
будет дешевле чем Postgres. Тогда пожалуй смысл есть.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974782
miroooha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mayton
miroooha, а покажи туловище парсера. Что у тебя там? JSoup? HtmlCleaner?

Простейший парсер на jsoup:
https://github.com/vonoriMMM/parser/blob/master/src/main/java/parser/googleplay/GooglePlayGamesParser.java
Даже safe-методы написал во избежание NPE. Но его все равно придется переписывать (какую-то часть), как только структура страницы изменится.

Была идея писать с помощью Selenium, но почему-то отказался, уж сам не помню из-за чего.
dakeiras
MongoDB не нужно использовать практически никогда. Это всё от нежелания учить SQL.

Довольно спорное заявление, но я отказался от Postgres из-за того, что при деплоее на heroku там проблемы с подключением были. Мне также говорили, зачем я пишу бота на Java, когда есть Python?
mayton
Возможно суммарная стоимость владения Монгой (если покупать ее как сервис у Амазона или Ажура)
будет дешевле чем Postgres. Тогда пожалуй смысл есть.

Монго даёт БД (кластер) бесплатную (Mongo Cloud) с объемом в 512 МБ и 500 подключений. Причем можно выбирать хост: Google/AWS/Azure. Для моих нужд более чем.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974787
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miroooha,

что-то у вас много слов и мало кода

никогда не испытывал проблем с upsert в MongoDB

покажите код сохранения

и почитайте документацию, тогда станет понятно, откуда берётся поле _id :
The _id FieldIn MongoDB, each document stored in a collection requires a unique _id field that acts as a primary key. If an inserted document omits the _id field, the MongoDB driver automatically generates an ObjectId for the _id field.

This also applies to documents inserted through update operations with upsert: true.

The _id field has the following behavior and constraints:
  • By default, MongoDB creates a unique index on the _id field during the creation of a collection.
  • The _id field is always the first field in the documents. If the server receives a document that does not have the _id field first, then the server will move the field to the beginning.
  • The _id field may contain values of any BSON data type, other than an array.
https://docs.mongodb.com/manual/core/document/

отдельно обращу ваше внимание на последней строке в цитате: The _id field may contain values of any BSON data type, other than an array .
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974788
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miroooha
Про второй случай. У меня же есть парсер, который по ссылке достаёт всю информацию об игре, которую я потом сохраняю в БД. Я знаю, что у меня в БД сейчас лежит объект, у которого тот же самый title, что и у игры, которую я парсю. Но одно поле у объекта, который лежит в БД и объекта, который я получил в ходе парсинга - разные.
Т.е. по идее всё должно сработать как и в первом сценарии - перезаписаться одно поле. Но здесь получаю DuplicateKey.

Значит в итоге вы делаете insert вместо update.

Если надо обновить одно поле в документе с соответствующим title , то выполните update с нужным set :

https://docs.mongodb.com/manual/reference/operator/update/set/
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974795
miroooha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий Мух
miroooha,

что-то у вас много слов и мало кода

никогда не испытывал проблем с upsert в MongoDB

покажите код сохранения

и почитайте документацию, тогда станет понятно, откуда берётся поле _id :
The _id FieldIn MongoDB, each document stored in a collection requires a unique _id field that acts as a primary key. If an inserted document omits the _id field, the MongoDB driver automatically generates an ObjectId for the _id field.

This also applies to documents inserted through update operations with upsert: true.

The _id field has the following behavior and constraints:
  • By default, MongoDB creates a unique index on the _id field during the creation of a collection.
  • The _id field is always the first field in the documents. If the server receives a document that does not have the _id field first, then the server will move the field to the beginning.
  • The _id field may contain values of any BSON data type, other than an array.
https://docs.mongodb.com/manual/core/document/

отдельно обращу ваше внимание на последней строке в цитате: The _id field may contain values of any BSON data type, other than an array .
Там почти нет кода. Используется готовый метод save() из MongoRepository. Я просто получаю объект из парсера и делаю на нём .save().
Я не писал реализацию для репозитория (интерфейса), используется дефолтная, так как думал, что для моих нужд этого будет достаточно, но возможно всё-таки придется, опыта набираться нужно.

Id у меня сейчас типа ObjectId, который относится к BSON типу, если я не ошибаюсь.

Проблема в обновлении в том, что там может быть такой сценарий, при котором надо обновлять не одно поле, а 10. Проще новый объект на место старого вставить?
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974796
miroooha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код есть, но как я уже сказал он предельно прост:
Сам документ:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "googleplaygames")
@Builder(builderClassName = "GooglePlayGameBuilder", toBuilder = true)
@AllArgsConstructor
@NoArgsConstructor
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)
public final class GooglePlayGame implements Serializable {
    @Id
    ObjectId id;
    @Indexed(unique = true)
    String title;
    String currentVersion
...


Репа:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
@Repository
public interface GooglePlayGamesRepository extends MongoRepository <GooglePlayGame, String> {

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

    List<GooglePlayGame> findByTitleContainsIgnoreCase(String gameTitle);

}


Сохранение в БД (с подменой Id, описанной выше):
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
try {
    googlePlayGamesRepository.save(googlePlayGame);
}
catch (org.springframework.dao.DuplicateKeyException e) {
       GooglePlayGame game = googlePlayGamesRepository.findByTitleIgnoreCase(googlePlayGame.getTitle());
       googlePlayGame.setId(game.getId());
       googlePlayGamesRepository.save(googlePlayGame);
}


Знаю, что некрасиво (мне самому не нравится), но пока так.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974912
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miroooha
Там почти нет кода. Используется готовый метод save() из MongoRepository. Я просто получаю объект из парсера и делаю на нём .save().
Я не писал реализацию для репозитория (интерфейса), используется дефолтная, так как думал, что для моих нужд этого будет достаточно, но возможно всё-таки придется, опыта набираться нужно.
MongoDB, как и другие СУБД, позволяет выполнить обновление не только по ключу, но и по условию.
В том числе и изменить документ с таким-то title . Причём как весь объект, так и только часть полей.

Все операции описаны в документации (например update ) и доступны через драйвер.

MongoRepository - это обёртка над драйвером MongoDB.

Предположу, что метод .save() работает исключительно по ключу (_id).
И когда последний есть, то выполняется update , а когда нет, как при получении объекта из парсера, то insert .
Отсюда вы и получаете DuplicateKey exception , потому как пытаетесь вставить новый документ, нарушающий уникальность индекса по полю title .

Вам нужно выполнить update не по ключу, а по условию title равно что-то там.
Посмотрите, если соответсвующий метод в вашем MongoRepository, возможно есть перегрузка метода .save(), принимающая не только документ, или аннотация какая.

Если же нет, то придётся написать свою реализацию репозитория, или использовать драйвер напрямую.

Вообщем читайте документацию как по MongoDB, так и по тем библиотекам, что используете для работы с ней.

miroooha
Id у меня сейчас типа ObjectId, который относится к BSON типу, если я не ошибаюсь.
Да, как и множество других типов: https://docs.mongodb.com/manual/reference/bson-types/
Среди которых и String , что также можно использовать в качестве значения _id .

miroooha
Проблема в обновлении в том, что там может быть такой сценарий, при котором надо обновлять не одно поле, а 10. Проще новый объект на место старого вставить?
Через $set можно одно, и два, и 10 полей обновить.
И при этом действительно проще новый объект на место старого вставить.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974917
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miroooha
Сохранение в БД (с подменой Id, описанной выше):
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
try {
    googlePlayGamesRepository.save(googlePlayGame);
}
catch (org.springframework.dao.DuplicateKeyException e) {
       GooglePlayGame game = googlePlayGamesRepository.findByTitleIgnoreCase(googlePlayGame.getTitle());
       googlePlayGame.setId(game.getId());
       googlePlayGamesRepository.save(googlePlayGame);
}



Знаю, что некрасиво (мне самому не нравится), но пока так.

Да уж, вот вам ссылки на документацию по драйверу для Java:

http://mongodb.github.io/mongo-java-driver/4.0/apidocs/mongodb-driver-sync/index.html
http://mongodb.github.io/mongo-java-driver/4.0/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCollection.html
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974972
dakeiras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторДовольно спорное заявление, но я отказался от Postgres из-за того, что при деплоее на heroku там проблемы с подключением были. Мне также говорили, зачем я пишу бота на Java, когда есть Python?
Там на хероку всё автоматом подключается в Postgresql.

А спорить не надо. Я знаю о чём говорю и это подтверждено опытом. Mongodb приводит к очень плачевным результатам.
Хотя не так. Нежелание учиться и лень приводят к очень плачевным результатам.

Python говно хуже явы.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974976
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dakeiras
Mongodb приводит к очень плачевным результатам.

Интересно к каким?

6 лет как у нас MongoDB вполне успешно используется в продакшене.
Да, надо знать как оно устроено и как с ним работать.

А если что-то не уметь готовить, тогда да, результаты будут плачевные, в том числе и с Postgres.

Который мы кстати тоже вполне успешно используем в продакшене :)
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974979
miroooha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий Мух , спасибо за разъяснения!
Покопаюсь в документации.

Пока посмотрел метод save MongoRepository. С дефолтной реализацией он работает так:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
public <S extends T> S save(S entity) {

     Assert.notNull(entity, "Entity must not be null!");

     if (entityInformation.isNew(entity)) {
          return mongoOperations.insert(entity, entityInformation.getCollectionName());
     }

     return mongoOperations.save(entity, entityInformation.getCollectionName());
}


Вызывается или insert, если такой entity нет, либо save класса MongoTemplate.
Ну а там уже реализация посложнее, сходу не разобрался. Единственное, в этом методе save активно мелькает id.
Код: java
1.
Object id = saveDocument(collectionName, dbDoc, objectToSave.getClass());


А в saveDocument такое дело:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
if (!mapped.hasId()) {
	if (writeConcernToUse == null) {
		collection.insertOne(dbDoc);
	} else {
		collection.withWriteConcern(writeConcernToUse).insertOne(dbDoc);
	}
} else if (writeConcernToUse == null) {
	collection.replaceOne(mapped.getIdFilter(), dbDoc, new ReplaceOptions().upsert(true));
} else {
	collection.withWriteConcern(writeConcernToUse).replaceOne(mapped.getIdFilter(), dbDoc,
			new ReplaceOptions().upsert(true));
}
return mapped.getId();


Дальше лезть ёщё страшнее.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974983
dakeiras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий Мух
dakeiras
Mongodb приводит к очень плачевным результатам.

Интересно к каким?

6 лет как у нас MongoDB вполне успешно используется в продакшене.
Да, надо знать как оно устроено и как с ним работать.

А если что-то не уметь готовить, тогда да, результаты будут плачевные, в том числе и с Postgres.

Который мы кстати тоже вполне успешно используем в продакшене :)

я получил систему завязанную на монго, где он был не к месту. А как и в 90% случаев к месту была бы SQL база.
Пришлось к ней писать доп. систему с человеческой SQL базой.

Это спасло от многомилионных убытков. (Но не надолго как показала практика).
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974984
dakeiras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторДа, надо знать как оно устроено и как с ним работать.
кстати, как в этом монго сделать так чтобы большой объект файл с записями 100мб можно было сохранять?
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974988
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miroooha
Дмитрий Мух , спасибо за разъяснения!
Покопаюсь в документации.

Пока посмотрел метод save MongoRepository. С дефолтной реализацией он работает так:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
public <S extends T> S save(S entity) {

     Assert.notNull(entity, "Entity must not be null!");

     if (entityInformation.isNew(entity)) {
          return mongoOperations.insert(entity, entityInformation.getCollectionName());
     }

     return mongoOperations.save(entity, entityInformation.getCollectionName());
}



Вызывается или insert, если такой entity нет, либо save класса MongoTemplate.
Ну а там уже реализация посложнее, сходу не разобрался. Единственное, в этом методе save активно мелькает id.
Код: java
1.
Object id = saveDocument(collectionName, dbDoc, objectToSave.getClass());



А в saveDocument такое дело:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
if (!mapped.hasId()) {
	if (writeConcernToUse == null) {
		collection.insertOne(dbDoc);
	} else {
		collection.withWriteConcern(writeConcernToUse).insertOne(dbDoc);
	}
} else if (writeConcernToUse == null) {
	collection.replaceOne(mapped.getIdFilter(), dbDoc, new ReplaceOptions().upsert(true));
} else {
	collection.withWriteConcern(writeConcernToUse).replaceOne(mapped.getIdFilter(), dbDoc,
			new ReplaceOptions().upsert(true));
}
return mapped.getId();



Дальше лезть ёщё страшнее.

Ну видно же, что если isNew(entity), то insert. Если нет id, то тоже insert. Что и требовалось доказать

Отсюда и DuplicateKey exception по title.

Вам по идее вместо mapped.getIdFilter() нужен некий mapped.getTitleFilter(), тогда выполнив:
Код: java
1.
collection.replaceOne(mapped.getTitleFilter(), dbDoc, new ReplaceOptions().upsert(true));


вы получите то, что вам нужно: нет документа с таким title, он добавится; есть - обновится.

На writeConcern не обращайте внимание, оно вам не надо.
Разве что можете в документации почитать, что это такое и когда следует использовать: https://docs.mongodb.com/manual/reference/write-concern/
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974989
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dakeiras
авторДа, надо знать как оно устроено и как с ним работать.

кстати, как в этом монго сделать так чтобы большой объект файл с записями 100мб можно было сохранять?
Как как... GridFS is a specification for storing and retrieving files that exceed the BSON-document size limit of 16 MB.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974991
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dakeiras
Дмитрий Мух
пропущено...

Интересно к каким?

6 лет как у нас MongoDB вполне успешно используется в продакшене.
Да, надо знать как оно устроено и как с ним работать.

А если что-то не уметь готовить, тогда да, результаты будут плачевные, в том числе и с Postgres.

Который мы кстати тоже вполне успешно используем в продакшене :)

я получил систему завязанную на монго, где он был не к месту. А как и в 90% случаев к месту была бы SQL база.
Пришлось к ней писать доп. систему с человеческой SQL базой.

Это спасло от многомилионных убытков. (Но не надолго как показала практика).

То есть вам досталась система на MongoDB, вы перенесли её на SQL базу... И в итоге получили убытки?

Простите, но мне видится, что проблема тут не в MongoDB.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974994
dakeiras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий Мух
dakeiras
пропущено...

кстати, как в этом монго сделать так чтобы большой объект файл с записями 100мб можно было сохранять?

Как как... GridFS is a specification for storing and retrieving files that exceed the BSON-document size limit of 16 MB.

я это видел. Как существующую базу\приложение на это мигрировать?

авторТо есть вам досталась система на MongoDB, вы перенесли её на SQL базу... И в итоге получили убытки?

Простите, но мне видится, что проблема тут не в MongoDB.
Не перенесли а дуплицировали данные, OLAP.

Но проблема и правда не в монго, как я выше и написал. Проблема в том что не нужно было его использовать изначально.
Это объектная БД, она не приспособлена для 90% случаев работы например в банковоской сфере.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39974997
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dakeiras
Дмитрий Мух
пропущено...

Как как... GridFS is a specification for storing and retrieving files that exceed the BSON-document size limit of 16 MB.

я это видел. Как существующую базу\приложение на это мигрировать?

Тут я вам сходу не скажу, я же не видел вашу базу\приложение.

Вопрос из разряда: как мигрировать приложение, что хранит файлы на сетевой шаре в Amazon S3.
Зависит от того, как это самое приложение спроектировано и реализовано.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39975002
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне кажется что количество "миграторов" в нашем мире
пропорционально количеству систем в квадрате.

А квадрат - это нехорошее число. Растет слишком резко. Не угонимся за всеми.

Тогда вместо того чтобы гуглить или ждать специфичный мигратор,
можно взять ... и написать свой.

Я не думаю что это сложно. На мой взгляд - курсовая для 2 курса
факультета ПО.
...
Рейтинг: 0 / 0
Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
    #39975004
Дмитрий Мух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
Я не думаю что это сложно. На мой взгляд - курсовая для 2 курса
факультета ПО.

Мне вот тоже кажется, что это не сложно, если приложение хорошо спроектировано.
Если же там некий SmartUI монолит, это уже вопрос
...
Рейтинг: 0 / 0
25 сообщений из 78, страница 2 из 4
Форумы / Java [игнор отключен] [закрыт для гостей] / Поле объекта в качестве уникального ключа в документе MongoDB (Spring Data)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]