Можно ли написать запрос в ydn-db, аналогичный SQL IN или нескольким предложениям AND?

Я пытаюсь написать запрос, который в SQL будет выглядеть примерно так:

select * from WorkOrder wo
    where wo.userId = 1
    and wo.isSynced = 0
    and wo.status in ('COMPLETE', 'REJECTED', 'SUSPENDED_NO_ACCESS', 'SUSPENDED_OTHER');

Я добавил индекс для userId, isSynced и статуса.

Если я создам запрос, подобный следующему, он будет работать до тех пор, пока я фильтрую только два разных значения статуса. Как только я добавляю 3 или более, он не возвращает никаких результатов. Я делаю что-то не так или мне нужно подходить к этому совершенно по-другому?

//this works
var keyRange = ydn.db.KeyRange.bound([userId, 0, Status.Complete],
            [userId, 0, Status.REJECTED]);
//this doesn't work
var keyRange = ydn.db.KeyRange.bound([userId, 0, Status.Complete],
            [userId, 0, Status.Suspended_AccessUnavailable],
            [userId, 0, Status.REJECTED]);


var iterator = new ydn.db.IndexValueIterator(Store.WorkOrder, 'userId, isSynced, status', keyRange);

return db.values(iterator)

person gusgorman    schedule 05.09.2014    source источник


Ответы (1)


В настоящее время множественный запрос («IN») и самообъединение («И») выполняются вручную и требуют большого количества шаблонов для их выполнения. Для сложного запроса, такого как в этом случае, потребуется сортировка в памяти с использованием ydn.structs.Buffer.

Используйте сортированное слияние или зигзагообразное слияние для самостоятельного объединения.

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

var iters = [];
var keys = ['COMPLETE', 'REJECTED', 'SUSPENDED_NO_ACCESS', 'SUSPENDED_OTHER'];
for (var i = 0; i < keys.length; i++) {
  iters[i] = ydn.db.IndexValueIterator.where('WorkOrder', 'status', '=', keys[i]);
});
var results = [];
db.scan(function(cursors) {
   // here we have four cursors for respective four index keys.
   // calculate lowest key(s) and put into result
   var min_i = ...
   results.push(cursors[i].getValue());
   // prepare next cursor iteration, 
   var next_position = [];
   next_position[min_i] = true; // advance lowest cursor to next position, while keeping the rest of cursor hold in current position.
   return next_position;
}, iters, 'readonly', ['WorkOrder']).then(function() {
   // use results
   console.log('results', results);
}, function(e) {
   console.error(e.stack);
});

Нетрудно сделать оболочку для приведенного выше кода, чтобы библиотека в конечном итоге поддерживала, например:

 var query = db.from('WorkOrder').where('status', 'in', ['COMPLETE', 'REJECTED', 'SUSPENDED_NO_ACCESS', 'SUSPENDED_OTHER']);
 query.list().then(function() {
   // use results
   console.log('results', results);
}, function(e) {
   console.error(e.message);
});
person Kyaw Tun    schedule 05.09.2014
comment
Спасибо за ответ. Честно говоря, я не все понял, поэтому просто выполнил несколько запросов, а затем объединил результаты в памяти. - person gusgorman; 16.09.2014
comment
Извините за трудность... но это типичная проблема с базами данных без sql? Я вообще не считаю это сложным запросом... было бы это возможно, если бы я использовал IndexedDb напрямую, а не через библиотеку-оболочку? - person gusgorman; 18.09.2014