You do it by chaining GetStored methods:

Class Document Extends %Persistent {

Property Filename As %VarString;

}

Class Question As %Persistent {

// Or relationship
Property Document As Document;

Property Filename As %String [ Calculated, SqlComputeCode = {set {*}=##class(Document).FilenameGetStored({Document})}, SqlComputed ];

}

Try it like this:

Class User.ResultsMessage Extends (%Persistent, %XML.Adaptor)
{

Property PersonIDs As list Of %String(XMLITEMNAME = "PersonID", XMLNAME = "PersonIDs", XMLPROJECTION = "WRAPPED");

XData Data
{
<Results>
  <PersonIDs>
    <PersonID>1000000</PersonID>
    <PersonID>1000001</PersonID>
    <PersonID>1000005</PersonID>
  </PersonIDs> 
</Results>
}

/// do ##class(User.ResultsMessage).Test()
ClassMethod Test()
{
	Set text = ##class(%Dictionary.XDataDefinition).IDKEYOpen($classname(), "Data").Data
	Set reader = ##class(%XML.Reader).%New()
	Set sc=reader.OpenStream(text)

	Do reader.Correlate("Results","User.ResultsMessage") 
	While reader.Next(.msg,.sc) {
		Write !,"Count(): "_msg.PersonIDs.Count(),!
	}
	Write:$$$ISERR(sc) $System.Status.GetErrorText(sc)
}
}

Docs.

You can use this syntax on calculated properties:

/// This property holds the document state. Serialization is JSON. 
Property JSON As %Library.DynamicAbstractObject;

/// This is an automatically calculated property "$.firstName"
Property firstName As %VarString [ SqlComputeCode = { set {*}=$$%EvaluatePathOne^%DocDB.Document({JSON},"$.firstName")}, SqlComputed, SqlComputeOnChange = %Doc ];

/// Index on firstName property
Index firstName On firstName;

1. Implement %iFind.Transformation.Abstract interface with the custom transformation that would remove all property names (I assume you know property names beforehand).

After that set TRANSFORMATIONSPEC index parameter to your transformation implementation.

2. Maybe User Dictionaries could also be used.

3. Are you sure you need analytic queries? Simpler iFind indices (Minimal, Basic) can be advantageous in some situations.

Calling @Benjamin De Boe