Moja aplikacja zapisuje wiele typów dokumentów w tym samym segmencie. Wiem, że to nie jest dobra praktyka, ale mam limit ilości wiaderek, które mogę utworzyć na moim serwerze, i nie ma na to czasu. Dokumenty są poprzedzone ich typami, więc kiedy dostaję dokument, muszę po prostu połączyć prefiks i id, aby uzyskać klucz i mogę wykonać kluczowe wyszukiwanie.Jak scalić dane w Couchbase z redukcją mapy?
Potrzebuję utworzyć raport zawierający informacje z więcej niż jednego typu dokumentu.
Moja mapa wygląda następująco:
function(doc, meta) {
var getStep = function(stepName, exit, mapper) {
if (meta.id.indexOf(stepName) !== -1) {
var hotelId = parseInt(meta.id.replace(stepName + '_', ''));
if (hotelId > 0) {
var result = {
hotelId: hotelId,
exit: exit
};
if (mapper !== undefined) {
mapper(result);
}
return result;
}
}
return null;
};
var photos = getStep('PHOTOS', 7);
if (photos != null) {
emit(photos.hotelId, photos);
}
var pricing = getStep('PICR', 5);
if (pricing != null) {
emit(pricing.hotelId, pricing);
}
var owner = getStep('OWNER', 1);
if (owner != null) {
emit(owner.hotelId, owner);
}
var amenity = getStep('AM', 4);
if (amenity != null) {
emit(amenity.hotelId, amenity);
}
var description = getStep('HDESC', 3, function(result) {
result.description = doc.description;
result.hotelRoomTypeId = doc.hotelRoomTypeId;
result.starRating = doc.starRating;
});
if (description != null) {
emit(description.hotelId, description);
}
var contact = getStep('DC', 3, function(result) {
result.email = doc.emailAddress;
result.contact = doc.mainContactName;
});
if (contact != null) {
emit(contact.hotelId, contact);
}
var location = getStep('LOC', 2, function(result) {
result.city = doc.cityName;
result.zip = doc.postalCode;
result.country = doc.countryName;
result.street = doc.stateName + ', ' + doc.streetName;
});
if (location != null) {
emit(location.hotelId, location);
}
var property = getStep('PRP', 1, function(result) {
result.paymentMethodId = doc.paymentMethodId
});
if (property != null) {
emit(property.hotelId, property);
}
}
Generuje to wyjście:
"total_rows":...,"rows":[
{"id":"DC_1","key":1,"value":{"hotelId":1,"exit":3,"email":"[email protected]","contact":"Jeno"}},
{"id":"HDESC_1","key":1,"value":{"hotelId":1,"exit":3,"description":".","hotelRoomTypeId":0,"starRating":5}},
{"id":"LOC_1","key":1,"value":{"hotelId":1,"exit":2,"city":"Barcelona","zip":"1222","country":"Spain","street":"Catalonia, someplacenice"}},
{"id":"PRP_1","key":1,"value":{"hotelId":1,"exit":1}},
{"id":"PRP_2","key":2,"value":{"hotelId":2,"exit":1}},
{"id":"AM_3","key":3,"value":{"hotelId":3,"exit":4}},
{"id":"AM_4","key":4,"value":{"hotelId":4,"exit":4}},
{"id":"PHOTOS_4","key":4,"value":{"hotelId":4,"exit":7}},
{"id":"PRP_4","key":4,"value":{"hotelId":4"exit":1}},
{"id":"AM_4","key":4,"value":{"hotelId":4,"exit":4}},
{"id":"PRP_4","key":4,"value":{"hotelId":4,"exit":1}},
{"id":"PHOTOS_5","key":5,"value":{"hotelId":5,"exit":7}}
...
]
Próbuję grupy datę, hotelId który jest nowy klucz i scalania pól do jednego dokumentu z niestandardowym reduktorem. Dostaję różne błędy w zależności od typu błędu, ale wszystkie błędy wydają się wskazywać, że istnieje limit daty zwrotu reduktora. Jeśli zmienię typ zwracany z obiektu na tablicę asocjacyjną, która działa w podobny sposób, otrzymuję lepszy błąd.
function(key, values, rereduce) {
if (rereduce) {
return values;
} else {
var results = {}; // Object!
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (!results[row.hotelId]) {
results[row.hotelId] = {
phone: '',
exit: 1
};
}
var result = results[row.hotelId];
for (var name in row) {
result[name] = row[name];
}
if (row.exit > row.exit) {
result.exit = row.exit;
}
};
return results;
}
}
Daje mi RangeError: Maximum call stack size exceeded
function(key, values, rereduce) {
if (rereduce) {
return values;
} else {
var results = []; // Array!
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (!results[row.hotelId]) {
results[row.hotelId] = {
phone: '',
exit: 1
};
}
var result = results[row.hotelId];
for (var name in row) {
result[name] = row[name];
}
if (row.exit > row.exit) {
result.exit = row.exit;
}
};
return results;
}
}
Daje mi reduction too large error
function(key, values, rereduce) {
if (rereduce) {
return values;
} else {
return values;
}
}
Daje mi RangeError: Maximum call stack size exceeded
Jeśli biegnę:
function(key, values, rereduce) {
if (rereduce) {
return values;
} else {
return values.length;
}
}
wrócę:
[ 68, 72, 65, 66, 68, 68, 70, 114 ]
Silnik JavaScript powinien być w stanie zmniejszyć tablice z max 114 rozmiarów i danych wyjściowych powinny być jeszcze mniejsze. Wygląda na to, że istnieje limit ilości danych, które redukują, mogą zwrócić max_kv_size_per_doc
, co oznacza 1 MB, a także istnieje limit 10 sekund wykonania, ale w moim przypadku jest to coś innego. Czy istnieje sposób, aby ominąć te ograniczenia, zmieniając algorytm, zwracając tablicę lub tablice lub coś takiego? Czy jest coś, co mogę zrobić na mapie lub jakieś sztuczki, których mogę użyć w rereduce?
a) posiadania wielu typów dokumentów w wiadrze nie jest złą praktyką; jest bardzo powszechny i często polecany. –
b) z jakiej wersji Couchbase korzystasz? czy N1QL nie jest dla ciebie opcją? –
c) "Przekroczony maksymalny rozmiar stosu połączeń" brzmi jak błąd JavaScript; najlepiej można debugować go i dowiedzieć się, skąd pochodzi, ale nie wiem, jak to zrobić, –