The first thing you'd need to do is define thisProperty to be a nested type instead of a regular object. Without defining thisProperty as nested, the relationship between the id and other_id pairs is lost. The docs go into more details on that topic. The resulting mapping would look like this:
{
"mappings": {
"type": {
"properties": {
"thisProperty": {
"type": "nested",
"properties": {
"id": {
"type": "keyword"
},
"other_id": {
"type": "keyword"
}
}
}
}
}
}
}
Next, you could use a nested aggregation to aggregate on the nested objects. The goal here is to find duplicate objects, which is something you could achieve by running a scripted terms aggregation that concatenates the document's _id, the value of id and of other_id. If we find any duplicates of the resulting concatenated field, we know that this document has a repeating set of properties. Adding "min_doc_count": 2 to the terms aggregation will allow you to see just those duplicates.
Putting all of this together would look like this:
GET test/_search
{
"size": 0,
"aggs": {
"my_nested": {
"nested": {
"path": "thisProperty"
},
"aggs": {
"dupes": {
"terms": {
"script": """return doc['_id'].value + "_" + doc['thisProperty.id'].value + "_" + doc['thisProperty.other_id'].value;""",
"size": 100,
"min_doc_count": 2
}
}
}
}
}
}
If your original document had an _id of 1, the resulting output of this aggregation would return:
"buckets": [
{
"key": "1_456_123",
"doc_count": 2
}
]
... telling you that document 1 has a duplicate set of properties where id is 456 and other_id is 123`.