Запрос на упорядочение отношений возвращает дубликаты данных

#javascript #node.js #sequelize.js

Вопрос:

Я запрашиваю заказы клиентов для указанного клиента, используя отношения Sequelize.

index.js

 var results2 = await customerService.getOrders(1);
console.log(results2);   
 

service.js

 exports.getOrders = function (id) {
    return customerModel.findAll({
        raw: true,
        include: [{
            model: orderModel,
            where: { customer_idcustomer: id }
        }],

    }).then(r => r);
};
 

Результаты

 [ { idcustomer: 1,
    customername: 'hello world',
    'orders.idorder': 1,
    'orders.orderdesc': 'order description 1',
    'orders.customer_idcustomer': 1 },
  { idcustomer: 1,
    customername: 'hello world',
    'orders.idorder': 2,
    'orders.orderdesc': 'Test 456',
    'orders.customer_idcustomer': 1 },
  { idcustomer: 1,
    customername: 'hello world',
    'orders.idorder': 3,
    'orders.orderdesc': 'Test 123',
    'orders.customer_idcustomer': 1 } ]
 

ожидаемый

 [ { idcustomer: 1,
    customername: 'hello world',
    'orders: [{
       'orders.idorder': 1,
       'orders.orderdesc': 'order description 1',
       'orders.customer_idcustomer': 1 },   
    },
    {
       'orders.idorder': 2,
       'orders.orderdesc': 'order description 2',
       'orders.customer_idcustomer': 1 },   
    },
    {
       'orders.idorder': 3,
       'orders.orderdesc': 'order description 3',
       'orders.customer_idcustomer': 1 },   
    }]
]
 

Ответ №1:

Все, что вам нужно, это удалить raw: true, из запроса ,

так как он вернет обычный/плоский объект , и это преобразует ваш объект так, как он выглядит сейчас.

 exports.getOrders = function (id) {
    return customerModel.findAll({
        // raw: true, // <------ Just remove this line
        include: [{
            model: orderModel,
            where: { customer_idcustomer: id }
        }],

    }).then(r => r);
};
 

Примечание : Вы должны поместить условие where на верхний уровень в соответствии с вашей
логикой

 exports.getOrders = function (id) {
    return customerModel.findAll({
        where: { id: id } ,
        // raw: true, // <------ Just remove this line
        include: [{
            model: orderModel
        }]
    }).then(r => r);
};
 

Комментарии:

1. Я получаю metadata customer заказы и следующее для заказов [[Order],[Order]]

2. @rod , это внутри консоли , если вы хотите увидеть полный ответ, сделайте JSON.stringify(your_obj) и console это, вы поймете идею.

3. Ах, ok…so если это для конечной точки API, я бы закодировал ее так }).then(r => JSON.stringify(r)); ?

4. @rod , нет, он вернет те же данные , что и вы хотели, но они не будут отображаться в консоли, чтобы увидеть, что в консоли нужно делать только вам JSON.stringify , понимаете мою точку зрения ?

5. ладно, думаю, теперь я понимаю. я протестировал через веб — браузер и понял, что вы имеете в виду. Спасибо

Ответ №2:

Попробуйте удалить raw значение ключа из вашего запроса.

Методы поиска предназначены для запроса данных из базы данных. Они не возвращают простые объекты, а вместо этого возвращают экземпляры модели. Поскольку методы finder возвращают экземпляры модели, вы можете вызвать любой элемент экземпляра модели в результате, как описано в документации по экземплярам.

Если вы хотите получить данные без информации о мета/модели, затем сопоставьте свои результаты с помощью

 { plain: true }
 

Хорошие примеры продолжения в документах

Пример:

 const getPlainData = records => records.map(record =>
  record.get({ plain: true }));

// Your code
return customerModel.findAll({
        // raw: true, <= remove
        include: [{
            model: orderModel,
            where: { customer_idcustomer: id }
        }],

    }).then(getPlainData);
 

Ответ №3:

В моем случае, имея

 raw: true
 

в вариантах не было никакой разницы.

Я добавил

 distinct: true 
 

и проблема исчезла.

Хотя я и употреблял findAndCountAll .

Документация: https://sequelize.org/master/class/lib/model.js~Model.html