Get many documents each with a specific "from" and "to" pair of fields

I have a collection of documents that holds the distance of locations like so:
{ "from": 1234, "to" : 5678, "distance": 200 }

I’d like to get many documents by specifying multiple from-to pairs in a single query. I see there is an $in keyword, but this doesn’t help in a pair scenario.

I do not really see any other way than using an outer $or for each of the multiple pair. Something like:

{ "$or" : [
    { "from" : 1234 , "to" : 5678 } ,
    { "from" : 5600 , "to" : 7800 } ,
    /* more pairs */
    { "from" : 3690 , "to" : 9999 }
] }
1 Like

Thanks, this seems like a solution too, but I actually went on a different route and created another field called from_to, which holds the concatenated string of from and to. That way I have a single field to search on.
Thank you!

I have never been a big fan of duplicating or mangling data to ease writing queries. Your concatenation increases your data size, increases your indexes size, introduces a second way to query the same information (unless you never have to query “from” only or “to” only) and someday, someone, somewhere will update “from” or “to” without modifying the concatenated form and you will have a bug.

The above being out, the $or way is the way to go without modifying your data model. It was not clear from your original post that was one of the avenue you were willing to take.

A better schema change that does not duplicate data, that allows a single field query with $in while keeping the simplicity of querying on “from” only or “to” only is to move the fields into a separate object.

So rather than

{ "from": 1234, "to" : 5678, "distance": 200 }

you would have

{ "segment" : { "from" : 1234 , "to" : 5678 } , "distance" : 200 } 

Then a the $or query above could become the following $in query:

{ "segment" : { "$in" : [
    { "from" : 1234 , "to" : 5678 } ,
    { "from" : 5600 , "to" : 7800 } ,
    /* more pairs */
    { "from" : 3690 , "to" : 9999 }
] } }

This is when lightning strike and we all realized that $in is a glorified $or.

But his is too verbose to my liking. Personally, I would forgo the “from” and “to” name an use an array such as:

{ "segment" : [ 1234 , 5678 ] , "distance" : 200 } 

or

{ "from_to" : [ 1234 , 5678 ] , "distance" : 200 } 

to realize that this would give a formal concatenation without duplication. Allowing query like

{ "from_to.0" : 1234 } /* to get all documents from the point 1234 */
{ "from_to.1" : 5678 } /* to get all documents to the poing 5678 */

The $in will then became:

{ "from_to" : { "$in" : [
    [ 1234 , 5678 ] ,
    [ 5600 , 7800 ] ,
    /* more pairs */
    [ 3690 , 9999 ]
] } }

All this is good but may be the real best model modification would be to use

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.