Могу ли я заказать документы CouchDB по общим ключам? - PullRequest
1 голос
/ 13 декабря 2010

Это мой первый вопрос здесь о stackoverflow, поэтому я надеюсь, что я следую правильному протоколу.

Я создаю простую браузерную игру на основе CouchDB и NodeJS. В моей игре пользователи могут иметь несколько персонажей. Я решил отделить игроков от их персонажей в базе данных, потому что мне редко нужно связывать данные учетной записи пользователя (электронная почта, настоящее имя и т. Д.) С данными их персонажей. В любом случае, вот моя проблема:

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

Вот мой код:

Функция (док) { выделять (док. владелец, док); } * +1010 *

Я пытаюсь получить такой результат (обратите внимание, это упрощено; я знаю, что CouchDB включает в вывод другие данные):

{
    "player1":{
        "character1":{
            "data":{}
        },
        "character2":{
            "data":{}
        }
    },
    "player2":{
        "character1":{
            "data":{}
        },
        "character2":{
            "data":{}
        }
    }
}

Ключи должны быть уникальными? Даст ли мой код желаемый результат?

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

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

Другое возможное решение - сохранить _id каждого символа, которым пользователь управляет, как свойство в базе данных учетных записей пользователей. Это кажется мне достаточно разумным, но если есть другой вариант или, я бы сказал, «лучший» вариант, я бы с удовольствием его услышал.

Как лучше всего решить эту проблему?

Заранее большое спасибо за помощь.

1 Ответ

4 голосов
/ 13 декабря 2010

Вы на правильном пути.Если вы хотите сделать это с уменьшением, вы можете определить эту карту:

function(doc) { 
  var r = {}, c = {}; 
  c[doc._id] = doc;
  r[doc.owner] = c; 
  emit(doc.owner,r); 
}

И это уменьшение:

function(k,v,red) {
  var r = {};
  for (var i in v) {
    for (var owner in v[i]) {
      if (!(owner in r)) r[owner] = {};
      for (var character in v[i][owner])
        r[owner][character] = v[i][owner][character];
    }
  }
  return r;
}

Это должно вернуть непосредственно то, что вы просили, но вряд лиоптимально: представление должно хранить большое количество данных для частей Map и Reduce ...

Вместо этого я бы выбрал Map без Reduce, например:

function(doc) {
  emit(doc.owner,null);
}

Эта карта при запросе include_docs=true вернет строки, которые выглядят следующим образом:

[  
  { id : 'charid', key : 'playid', doc : { /* character document */ } },
  ...
]

Загрузка сервера меньше, и вы все равно можете перегруппировать персонажей по игроку, используя key врезультат, если вам действительно нужно.Результаты сортируются по key, затем по id.

Вы можете запросить это представление, используя startkey и endkey, оба равные идентификатору игрока, чтобы получить все символы, которые есть у игрока.Если вам нужны только идентификаторы символов, добавьте include_docs=false, а тяжелая часть doc не будет отправлена.

...