2017-07-07 13 views
6

Uygulamam, aynı grupta birden çok belge türü saklıyor. İyi bir uygulama olmadığını biliyorum, ancak sunucumda kaç tane kepçe oluşturabildiğim konusunda bir sınırım var ve şu anda bunun etrafında bir yol yok. Belgeler önekle yazılıyor, böylece bir belgeyi aldığımda sadece önek ile anahtarın yerini alması ve bende anahtar arama yapabilmem gerekiyor.Couchbase'deki veriler harita ile nasıl birleştirilir?

Birden çok belge türünden bilgi toplayan bir rapor oluşturmalıyım.

Haritamın şöyle görünür:

"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}} 
... 

] 

Ben gruba yeni anahtarıdır hotelId tarafından tarihini çalışıyor ve bir belgeye birleştirme alanları am:

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); 
    } 
} 

Bu çıktıyı üretir özel bir redüktör ile. Hata türüne bağlı olarak farklı hatalar alıyorum ama tüm hatalar redüktörün ne kadar geri dönebileceğine dair bir sınır olduğunu gösteriyor gibi görünüyor. Dönüş türünü bir nesneden hemen hemen aynı şekilde çalışan ilişkisel bir diziye değiştirirsem daha iyi bir hata alırım.

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; 
    } 
} 

Koşarsam reduction too large error

function(key, values, rereduce) { 
    if (rereduce) { 
    return values; 
    } else {  
    return values; 
    } 
} 

bana verir bana RangeError: Maximum call stack size exceeded

verir 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; 
    } 
} 

bana verir:

function(key, values, rereduce) { 
    if (rereduce) { 
    return values; 
    } else {   
    return values.length; 
    } 
} 

Ben dönene:

[ 68, 72, 65, 66, 68, 68, 70, 114 ] 

JavaScript motoru bile daha küçük olmalıdır maksimum 114 boyutu ve çıkış verileri ile diziler azaltmak gerekir. Görünüşe göre, bir azaltmanın ne kadar verinin max_kv_size_per_doc olduğunu ve 1Mb'nin de 10 saniyelik bir yürütme sınırlaması getirebileceğine dair bir sınır var ama benim durumumda başka bir şey. Algoritma, dizi veya diziler veya bir şey döndürerek bu sınırları aşmanın bir yolu var mı? Haritada yapabileceğim bir şey mi var, yoksa rıhtımda kullanabileceğim bazı hileler var mı?

+0

a) bir kova birden çok belge türlerini içeren bir kötü uygulama değildir; çok yaygın ve genellikle tavsiye edilir. –

+0

b) Hangi Couchbase sürümünü kullanıyorsunuz? N1QL sizin için bir seçenek değil mi? –

+0

c) "Maksimum çağrı yığını boyutu aşıldı" bir JavaScript hatası gibi geliyor; İdeal olarak bunun içinden hata ayıklayabilir ve nereden geldiğini öğrenebilirsiniz, ancak bu –

cevap

3

Bunu çözdüm. Bileşik anahtarları ve group_level kullanırsam çalışır.

yüzden otel kimliği için anahtar olarak bir dizi dönmek için benim haritayı değiştirmek ve ben başlangıçta beklendiği gibi group_level = 1 sonra değerler benim için gruplandırılacaktır ayarlarsanız:

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); // array as key 
    } 
    var pricing = getStep('PICR', 5); // array as key 
    if (pricing != null) { 
    emit([pricing.hotelId], pricing); 
    } 
    var owner = getStep('OWNER', 1); // array as key 
    if (owner != null) { 
    emit([owner.hotelId], owner); 
    } 
    var amenity = getStep('AM', 4); // array as key 
    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); // array as key 
    } 
    var contact = getStep('DC', 3, function(result) { 
    result.email = doc.emailAddress; 
    result.contact = doc.mainContactName; 
    }); 
    if (contact != null) { 
    emit([contact.hotelId], contact); // array as key 
    } 
    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); // array as key 
    } 
    var property = getStep('PRP', 1, function(result) { 
    result.paymentMethodId = doc.paymentMethodId 
    }); 
    if (property != null) { 
    emit([property.hotelId], property); // array as key 
    } 
} 

Sonra ayarlamanız gerekir group_level=1 ve reduce=true. Bunu görüntü düzenleyicide veya sorgu dizesinde yapabilirsiniz.

son bit azaltmak:

function(key, values, rereduce) { 
    if (rereduce) { 
    return values; 
    } else {   
    var result = {}; 
    values.forEach(function(item){ 
     for(var name in item){ 
      result[name] = item[name]; 
     } 
    }); 

    return result; 
    } 
} 

beklendiği gibi :) sonuç hotelId tarafından birleştirilecek