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