Querying and sorting whole embedded documents

SIMPLIFIED QUESTION
Why is this?

bsonWoCompare({foo: true}, {bar: “BAR”})
25
bsonWoCompare({foo: “”}, {bar: “BAR”})
1
bsonWoCompare({foo: MinKey()}, {bar: “BAR”})
-16

According to https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#objects both results should be positive, right? Field keys are compared first and foo > bar.

MORE DETAILED QUESTION
I have a single key-value pair embedded document, tag, that I’m treating as a tuple (basically). Example collection:

{_id: 1, tag: {bab: 123}}
{_id: 2, tag: {bar: "BAR"}}
{_id: 3, tag: {foo: "FOO"}}

I am trying to do a range query on the ENTIRE embedded document. For example:

{tag: {$gte: {foo: MinKey()}, $lte: {foo: MaxKey()}}  
// Values aren't always Min/MaxKey, but in this example, I'm trying to match any documents with the key "foo"

According to https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#objects:
1. Recursively compare key-value pairs in the order that they appear within the BSON object.
2. Compare the key field names.
3. If the key field names are equal, compare the field values.
4. If the field values are equal, compare the next key/value pair (return to step 1). An object without further pairs is less than an object with further pairs.

Other places I’ve been asking:
https://jira.mongodb.org/browse/SERVER-51258

Hi @Scott_Crunkleton and welcome in the MongoDB Community :muscle: !

I’m not really answering your question but here is the right way to find documents with a specific key in a sub-document:

test:PRIMARY> db.c.find()
{ "_id" : 1, "tag" : { "bab" : 123 } }
{ "_id" : 2, "tag" : { "bar" : "BAR" } }
{ "_id" : 3, "tag" : { "foo" : "FOO" } }
test:PRIMARY> db.c.find({"tag.foo": {$exists: 1}})
{ "_id" : 3, "tag" : { "foo" : "FOO" } }

What are you trying to do exactly?

Cheers,
Maxime.

I’ll try to give a better example of what I’m trying to do. Here is a simplified collection of medical patients:

{_id: 1, name: "foo", tags: [{bpSystolic: 120}, {bpDiastolic: 80}, {bloodGlucose: 86.4}]}
{_id: 2, name: "bar", tags: [{alert: true}, {bloodGlucose: 124.3}]}

With index:
{tags: 1}

As you can see, I have multiple tags (which I’m trying to treat as 2-tuples: key, value) on a patient. A tag key may or may not be present for a patient. Those that do exist, I would like to be sortable/range-queryable. Some example queries:

// Get patients with systolic blood pressure 150+.
{tags: {$elemMatch: {$gte: {bpSystolic: 150}, $lt: {bpSystolic: MaxKey()}}}}

// Get all patients that have a blood glucose reading.
{tags : {$elemMatch: {$gte: {bloodGlucose: MinKey()}, $lte: {bloodGlucose: MaxKey()}}}}

// Get all patients that have a blood glucose reading AND a systolic blood pressure reading.
{$and: [{tags : {$elemMatch: {$gte: {bloodGlucose: MinKey()}, $lte: {bloodGlucose: MaxKey()}}}}, {tags : {$elemMatch: {$gte: {bpSystolic: MinKey()}, $lte: {bpSystolic: MaxKey()}}}}]}

// Get patients with an alert.
{tags: {alert: true}}

// Sort patients by systolic blood pressure descending.
{tags : {$elemMatch: {$gte: {bpSystolic: MinKey()}, $lte: {bpSystolic: MaxKey()}}}} (sorted by {tags: -1})

A quick explanation for why I’m trying this route:
We have patients that need to be queried/ordered in a lot of different ways. I previously had created 30+ indexes to support those queries. I’m trying to merge these different data points into one indexed field, tags.