Say, I have two documents in a collection stored in the MongoDB
{
_id: ObjectId("64cfe7bf9f45fdfdb2eadcb2"),
userId: 101,
title: { value: 'mr', isSelected: true, position: 1 },
firstName: { value: 'John', isSelected: true, position: 4 },
middleName: { value: 'M.', isSelected: true, position: 2 },
lastName: { value: 'Doe', isSelected: true, position: 3 }
},
{
_id: ObjectId("64cfe7bf9f45fdfdb2eadcb3"),
userId: 102,
title: { value: 'ms', isSelected: true, position: 1 },
firstName: { value: 'Janna', isSelected: true, position: 2 },
middleName: { value: 'R', isSelected: true, position: 3 },
lastName: { value: 'Lee', isSelected: true, position: 4 }
}
I will pass the userId value to the query and in return I wanted the document to be returned with the document’s fields in an order defined in the position value.
Expected Result if userId is 101:
{
_id: ObjectId("64cfe7bf9f45fdfdb2eadcb2"),
userId: 101,
title: { value: 'mr', isSelected: true, position: 1},
middleName: { value: 'M.', isSelected: true, position: 2},
lastName: { value: 'Doe', isSelected: true, position: 3}
firstName: { value: 'John', isSelected: true, position: 4},
}
Note that field names are in different order (title, middleName, lastName, firstName).
And, if userID is 102 then:
{
_id: ObjectId("64cfe7bf9f45fdfdb2eadcb3"),
userId: 102,
title: { value: 'ms', isSelected: true, position: 1},
firstName: { value: 'Janna', isSelected: true, position: 2},
middleName: { value: 'R', isSelected: true, position: 3},
lastName: { value: 'Lee', isSelected: true, position: 4}
}
Notice the field names are in different order than the first query (title, firstName, middleName, lastName)
Thank you
2
Answers
To achieve the expected result, you can use MongoDB’s aggregation framework to sort the fields based on the
position
value. Here’s a sample query to accomplish this:Explanation of the query:
$match
stage filters the documents based on theuserId
.$project
stage selects the desired fields (_id
,userId
,title
,firstName
,middleName
,lastName
) and creates a field calledfieldOrder
which holds an array defining the order of the fields.$project
stage converts the document into an array of key-value pairs using$objectToArray
.$unwind
stage deconstructs the array created in the previous stage.$match
stage filters the unwound key-value pairs to only include those whose key ($documentFields.k
) is present in thefieldOrder
array.$group
stage groups the key-value pairs back into an array using theuserId
and_id
.$replaceRoot
stage promotes the array of key-value pairs back to an object, effectively reshaping the document with fields sorted based on theposition
.If I understand what you are trying to do (I usually avoid any object field ordering importance.), this aggregation pipeline may be sufficient. It’s a bit specific and not flexible, so it would need adjustment if the document model changes.
N.B.: Unfortunately the MongoDB Go driver that mongoplayground.net uses always does an alphanumeric sort of objects by field names, so demonstrating this there is problematic.