Whilst not being quite sure what you are trying to do, I suggest the following:
Create a document that acts as your mapping between the "@" tags in the string and fields within the MongoDB document.
Modify your Post document, so that the tags array contains standardized documents that both identify the _id values of the documents in which the real data is stored, and the field from which the data should be taken in these documents.
(Optionally) Modify your Post document, to explicitly contain the mapping document _id. If there is a global mapping document this would be unnecessary, but
In your example, the mapping document might look like:
Mapping: { _id: "abc..", maps: [{tag:"user", field:"user.person.nickname"}, {tag:"thing", field:"object.name"}] }
And the post document would look like:
Post: { _id: "48ajsdlfhsdjfkjsljsd",
name: "Post One",
text: "@user is the best for liking @thing, and @thing",
tags: [{tag:"user", docId:"pqr..."}, {tag:"thing", docId:"xzy..."}, {tag:"thing", docId:"mno..."}],
mapping: "abc..."
}
You will then need to do the following to return the text string:
- Load the Post document
- Extract and load the Mapping document (if this mapping is global, this step is not required)
Load all the documents corresponding to underlying data in one load:
db.posts.find( { _id: { $in : [ "pqr...", "xyz...", "mno..." ] } })
Retrieve the value from required document field from each of the located documents
- Replace the tag with the field value
This approach allows you to both change the meaning of the tag in the string (by changing the Mapping document - for example you could change @user from nickname to realname), and the value of the tag (by changing the docIds stored in the tags list within the Post document), but there are still a minimum of 4 steps to the string generation.
The approach does not handle the conditions where the Mapping document does not contain the tag, or when the tags list is not the same size as the number of tags in the text string.