MongoDB: Cómo acceder al padre de la lista cuando se usa $ where

Muestra de datos

{
  "Subject": "New thread"
  "Messages": [
    {
      "DateSent": "Mon, 16 May 2011 14:34:17 GMT -04:00",
    },
    {
      "DateSent": "Mon, 16 May 2011 14:59:57 GMT -04:00",
    }
  ],
  "Participants": [
    {
      "UserId": 2,
      "LastReadMessageIndex": 0,
    },
    {
      "UserId": 1,
      "LastReadMessageIndex": 1
    }
  ],
}

Un hilo contiene una lista de mensajes y una lista de participantes. Cuando un participante ve un hilo, LastReadMessageIndex se actualiza a la longitud de los mensajes.

Quiero recuperar la cantidad de hilos en los que hay mensajes no leídos para un participante determinado. Puedo usar la operación $ where dentro de mi lista de participantes de esta manera:

db.MessageThreads.find( {Participants: {$elemMatch: { UserId: 2, $where: {this.LastReadMessageIndex) < this.**parent**.Messages.length}}} }).count();

¿Es posible acceder al objeto principal?

preguntado el 16 de mayo de 11 a las 20:05

1 Respuestas

Creo que el problema que tienes aquí es que estás emparejando $elemMatch y $where. En el contexto de $where, El valor de this debe ser el documento en sí. Sin embargo, parece que estás diciendo que this es un subdocumento.

Aquí hay un código de muestra que hace lo que quiere:

unread = function () {
    for (var i in this.Participants) {
        if (this.Participants[i].UserId == 2 &&
            this.Participants[i].LastReadMessageIndex < this.Messages.length) {
                return true;
        }
    }
    return false;
}

db.MessageThreads.find(unread)

El único problema aquí es que he codificado el UserId a 2. Si planea llamar a esto desde uno de los controladores del cliente, tendrá que inyectar eso 2 en el lugar correcto.

Si parece un poco "hacky", lo es. Está tratando de comparar subdocumentos dentro de un solo documento y MongoDB no es muy bueno en esto y la estructura de su documento no lo hace fácil.

Es posible que desee considerar:

"Participants": {
  "2": { "LastReadMessageIndex": 0 },
  "1": { "LastReadMessageIndex": 1 }
}

Estos cambios no resolverán el problema por completo, pero facilitan mucho la consulta:

unread = function() { 
  return (this.Participants['2'].LastReadMessageIndex < 
    this.Messages.length);
}

Si se trata de una consulta importante, es posible que desee considerar la posibilidad de crear un Mapa / Reducir para este proceso.

contestado el 17 de mayo de 11 a las 01:05

Gracias. Tienes razón, cambiar la estructura tiene sentido y es más limpio. - Dan

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.