mapreduce ravendb ravenhq

mapreduce - RavenDB Map/Reduce/Transform en matrices anidadas de longitud variable



ravenhq (1)

Suponiendo que tus clases de C # se vean así:

public class Submission { public int SurveyId { get; set; } public int LocationId { get; set; } public IList<Answer> Answers { get; set; } } public class Answer { public int QuestionId { get; set; } public int[] Values { get; set; } public string Comment { get; set; } }

Si está ejecutando RavenDB 2.5.2637 o superior, ahora puede usar un tipo de resultado de diccionario:

public class Result { public int SurveyId { get; set; } public int QuestionId { get; set; } public int NumResponses { get; set; } public int NumComments { get; set; } public Dictionary<int, int> Values { get; set; } }

Si está ejecutando algo antes (incluidas las versiones 2.0), entonces no podrá usar un diccionario, pero puede usar un IList<KeyValuePair<int,int>> lugar.

Aquí está el índice:

public class TestIndex : AbstractIndexCreationTask<Submission, Result> { public TestIndex() { Map = submissions => from submission in submissions from answer in submission.Answers select new { submission.SurveyId, answer.QuestionId, NumResponses = 1, NumComments = answer.Comment == null ? 0 : 1, Values = answer.Values.ToDictionary(x => x, x => 1) //Values = answer.Values.Select(x => new KeyValuePair<int, int>(x, 1)) }; Reduce = results => from result in results group result by new { result.SurveyId, result.QuestionId } into g select new { g.Key.SurveyId, g.Key.QuestionId, NumResponses = g.Sum(x => x.NumResponses), NumComments = g.Sum(x => x.NumComments), Values = g.SelectMany(x => x.Values) .GroupBy(x => x.Key) .ToDictionary(x => x.Key, x => x.Sum(y => y.Value)) //.Select(x => new KeyValuePair<int, int>(x.Key, x.Sum(y => y.Value))) }; } }

(No se necesita paso de transformación).

Si no puede usar 2.5.2637 o superior, reemplace las líneas .ToDictionary con las líneas comentadas justo debajo de ellas, y use un IList<KeyValuePair<int,int>> en la clase de resultados.

La solución para permitir diccionarios en el mapa / reducir se basó en este problema que su publicación ayudó a identificar. ¡Gracias!

Soy nuevo en RavenDB, y lo amo hasta ahora. Tengo un índice restante para crear para mi proyecto.

El problema

Tengo miles de respuestas a encuestas (es decir, " Submissions "), y cada envío tiene una serie de respuestas a preguntas específicas (es decir, " Answers "), y cada respuesta tiene una matriz de opciones que se seleccionaron (es decir, " Values ").

Así es como se ve una Submission simple básicamente:

{ "SurveyId": 1, "LocationId": 1, "Answers": [ { "QuestionId": 1, "Values": [2,8,32], "Comment": null }, { "QuestionId": 2, "Values": [4], "Comment": "Lorem ipsum" }, ...more answers... ] }

Más problema: Tengo que poder filtrar por SurveyId, LocationId, QuestionId, Fecha de creación. Según tengo entendido, eso se hace en el momento de la consulta ... Solo necesito asegurarme de que estas propiedades estén presentes en el resultado de la transformación (¿o es el resultado de reducción? ¿O ambos?). Si estoy en lo cierto, entonces este es un problema menor.

El resultado requerido

Necesitamos un objeto por pregunta por encuesta que proporcione la suma de cada opción. Con suerte, se explica por sí mismo:

[ { SurveyId: 1, QuestionId: 1, NumResponses: 976, NumComments: 273, Values: { "1": 452, // option 1 selected 452 times "2": 392, // option 2 selected 392 times "4": 785 // option 4 selected 785 times } }, { SurveyId: 1, QuestionId: 2, NumResponses: 921, NumComments: 46, Values: { "1": 325, "2": 843, "4": 119, "8": 346, "32": 524 } }, ... ]

Mi intento

No llegué muy lejos, y creo que esta publicación me lleva por el camino correcto, pero no me ayuda con la lista de valores. He buscado y buscado, pero no puedo encontrar ninguna dirección sobre qué hacer con una matriz anidada como esa. Esto es lo que tengo hasta ahora:

MAPA:

from submission in docs.Submissions from answer in submission.Answers where answer.WasSkipped != true && answer.Value != null select new { SubmissionDate = submission["@metadata"]["Last-Modified"], SurveyId = submission.SurveyId, LocationId = submission.LocationId, QuestionId = answer.QuestionId, Value = answer.Value }

REDUCIR:

??

TRANSFORMAR:

from result in results from answer in result.Answers where answer.WasSkipped != true && answer.Value != null select new { SubmissionDate = result["@metadata"]["Last-Modified"], SurveyId = result.SurveyId, LocationId = result.LocationId, QuestionId = answer.QuestionId, Value = answer.Value }

Por lo que vale, esto está alojado en RavenHQ.

Ha pasado tanto tiempo que he estado trabajando en esto y no puedo hacerlo bien. ¡Cualquier ayuda para lograr el resultado requerido es muy apreciada!