Разделение пользовательской таблицы от людей таблица в реляционной базе данных

Лучший способ сделать это - использовать структуру агрегации для вычисления нашего нового поля.

MongoDB 3.4

Наиболее эффективное решение в MongoDB 3.4 с помощью $addFields и $out операторов конвейерной агрегации.

db.collection.aggregate(
    [
        { "$addFields": { 
            "name": { "$concat": [ "$firstName", " ", "$lastName" ] } 
        }},
        { "$out": "collection" }
    ]
)

Обратите внимание, что это не обновляет вашу коллекцию, а вместо этого заменяет существующую коллекцию или создает новый. Также для операций обновления, для которых требуется «литье типов», вам потребуется обработка на стороне клиента, и в зависимости от операции вам может понадобиться использовать метод find() вместо метода .aggreate().

MongoDB 3.2 и 3.0

. Мы делаем это с помощью $project наших документов и используем оператор агрегации строк $concat для возврата конкатенированной строки , we Оттуда вы затем перебираете курсор и используете оператор обновления $set , чтобы добавить новое поле в ваши документы, используя массовые операции для максимальная эффективность.

Запрос на агрегирование:

var cursor = db.collection.aggregate([ 
    { "$project":  { 
        "name": { "$concat": [ "$firstName", " ", "$lastName" ] } 
    }}
])

MongoDB 3.2 или новее

из этого, вам нужно использовать bulkWrite .

var requests = [];
cursor.forEach(document => { 
    requests.push( { 
        'updateOne': {
            'filter': { '_id': document._id },
            'update': { '$set': { 'name': document.name } }
        }
    });
    if (requests.length === 500) {
        //Execute per 500 operations and re-init
        db.collection.bulkWrite(requests);
        requests = [];
    }
});

if(requests.length > 0) {
     db.collection.bulkWrite(requests);
}

MongoDB 2.6 и 3.0

В этой версии вам необходимо использовать устаревший API Bulk и его связанные методы .

var bulk = db.collection.initializeUnorderedBulkOp();
var count = 0;

cursor.snapshot().forEach(function(document) { 
    bulk.find({ '_id': document._id }).updateOne( {
        '$set': { 'name': document.name }
    });
    count++;
    if(count%500 === 0) {
        // Excecute per 500 operations and re-init
        bulk.execute();
        bulk = db.collection.initializeUnorderedBulkOp();
    }
})

// clean up queues
if(count > 0) {
    bulk.execute();
}

MongoDB 2.4

cursor["result"].forEach(function(document) {
    db.collection.update(
        { "_id": document._id }, 
        { "$set": { "name": document.name } }
    );
})

9
задан Barrett Conrad 18 September 2008 в 03:13
поделиться

7 ответов

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

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

С точки зрения кодирования при использовании прямого SQL приложит немного больше усилий мысленно проанализировать избранный оператор. Это может быть немного более сложно, если Вы пользуетесь библиотекой ORM. У меня нет достаточного опыта с теми.

В моем приложении я пишу это в Ruby on Rails, таким образом, я постоянно делаю вещи как employee.user.name, где, если бы я держал их вместе, это было бы просто employee.name или user.name.

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

Вы могли также создать представление в базе данных для хранения обеих таблиц объединенными, чтобы дать Вам дополнительные улучшения производительности. Я знаю в более поздних версиях Oracle, можно даже поместить индекс на представление в случае необходимости для увеличения производительности.

8
ответ дан 3 November 2019 в 00:06
поделиться

Если бы user_tb имеет подлинную информацию, я очень разделил бы его от people_tb. Я однако сохранил бы отношения между этими двумя, и большая часть информации пользователей будет сохранена в people_tb кроме всей информации, необходимой для автора (который я предполагаю еще, не будет использоваться для очень), Это - хороший компромисс между дизайном и эффективностью, я думаю.

1
ответ дан 3 November 2019 в 00:06
поделиться

Я обычно делаю это, потому что для меня понятие о "пользователе" (имя пользователя, пароль, создают дату, последнюю дату входа в систему) отличается от "человека" (имя, адрес, телефон, электронная почта). Один из недостатков, которые можно найти, - то, что запросы будут часто требовать, чтобы больше соединений получило информацию, которую Вы ищете. Если все, что Вы имеете, будет именем для входа в систему, то необходимо будет присоединиться к "людям" таблица для получения имени и фамилии, например. При базировании всего вокруг первичного ключа идентификатора пользователя это смягчено немного, но все еще открывается.

3
ответ дан 3 November 2019 в 00:06
поделиться

Я всегда стараюсь избегать как можно большего повторения данных. Если не все люди должны войти в систему, у Вас может быть дженерик people таблица с информацией, которая относится и к людям и к пользователям (например, firstname, lastname, и т.д.).

Затем для людей, которые входят в систему, у Вас может быть a users таблица, которая имеет 1~1 отношение с people. Эта таблица может сохранить имя пользователя и пароль.

0
ответ дан 3 November 2019 в 00:06
поделиться

Я сказал бы, идут для нормализованного дизайна (две таблицы) и только денормализовывают (спуститесь до одной таблицы пользователя/человека), если это действительно сделает Вашу жизнь легче по линии. Если однако практически все люди являются также пользователями, может быть более просто денормализовать впереди. До Вас; я использовал нормализованный подход без проблем.

0
ответ дан 3 November 2019 в 00:06
поделиться

Очень разумный.

Как пример, смотрите на aspnet_* сервисные таблицы здесь.

Их созданный в схеме имеет a aspnet_Users и aspnet_Membership с более поздней таблицей, имеющей более расширенную информацию о данном пользователе (хешированные пароли, и т.д.), но aspnet_User.UserID используется в других частях схемы для ссылочной целостности и т.д.

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

0
ответ дан 3 November 2019 в 00:06
поделиться

Это определенно, что мы делаем, поскольку у нас есть миллионы людей записи и только тысячи пользователей. Мы также разделяем адрес, телефоны и электронные письма в реляционные таблицы, поскольку у многих людей есть больше чем одна из каждой из этих вещей. Critial не должен полагаться на имя как на идентификатор, поскольку имя не уникально. Удостоверьтесь, что к таблицам присоединяются через некоторый тип суррогатного ключа (целое число, или GUID предпочтителен), не, называют.

0
ответ дан 3 November 2019 в 00:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: