Trying to findOne document where a field (array) exactly matches another array


#1

Hi there, I’m trying to perform a findOne search in Meteor on a collection. I’d like to only return a document if the field (array) exactly matches the array i"m querying against.

On Stack Overflow I’ve been advised to try $all but that only matches if the array is in the same order.

existingThread = MessageThreads.findOne participants: $all: participants

The other advice was to combine $size with $in but for some reason a document gets returned if the $size OR $in matches.

existingThread = MessageThreads.findOne participants:
    $size: participantCount
    $in: participants

A typical messageThread document would look like this:

{
  "_id" : "j4tkc8uAtLffcc23X",
  "creator" : "SNhRq4vQpwFBjnTSH",
  "participants" : [
    "RLmnidY6GypdqDXZu",
    "HZzTztgdNG4BFETNw",
    "6WKrZoxvRj7w59oTA",
    "SNhRq4vQpwFBjnTSH"
  ],
  "messages" : [
    {
      "sender" : "SNhRq4vQpwFBjnTSH",
      "content" : "here is a message",
      "createdAt" : ISODate("2015-11-22T17:34:53.342Z")
    },
    {
      "sender" : "SNhRq4vQpwFBjnTSH",
      "content" : "here is another message",
      "createdAt" : ISODate("2015-11-22T17:34:53.342Z")
    }
  ]
}

The idea is that to my method I pass in an array of ids from the to field on my form. The method then checks if there are any current threads that have exactly the same user ids, if so it adds a new message to that thread, if not it creates a new thread.

Any help would be much appreciated.


#2

Have you tried $and?


#3

Thanks @repjackson, could you advise further? Would that entail splitting the query up into two parts?


#4
MessageThreads.findOne participants:
  { $and: [ 
    { "participants": "RLmnidY6GypdqDXZu" }, 
    { "participants": "HZzTztgdNG4BFETNw" }, 
    { "participants": "6WKrZoxvRj7w59oTA" }, 
    { "participants": "SNhRq4vQpwFBjnTSH" }, 
    { "participants": { $size: 4 }} 
  ] }

I would tyr something like this


#5

Thanks @shock, I already have an array of participants so not sure how I’d go about looping through them from within the query


#6

You will not be looping over them in query, but you prepare selector in advance and pass it to findOne

for example

_.map(participantArray, (item) ->
  return {
    participants: item
  }
)