首页 文章

MongoDB查找子文档并对结果进行排序

提问于
浏览
1

我在MongoDB中有一个具有复杂结构和子文档的集合 . 该文档的结构如下:

doc1 = {
    '_id': '12345678',
    'url': "http//myurl/...",
    'nlp':{
        "status": "OK",
        "entities": {
            "0": {
                "type" : "Person",
                "relevance": "0.877245",
                "text" : "Neelie Kroes"
            },
            "1": {
                "type": "Company",
                "relevance": "0.36242",
                "text": "ICANN"
            },
            "2": {
                "type": "Company",
                "relevance": "0.265175",
                "text": "IANA" 
            }
        }
    }
}


doc2 = {
    '_id': '987456321',
    'url': "http//myurl2/...",
    'nlp':{
        "status": "OK",
        "entities": {
            "0": {
                "type": "Company",
                "relevance": "0.96",
                "text": "ICANN"
            },
            "1": {
                "type" : "Person",
                "relevance": "0.36242",
                "text" : "Neelie Kroes"
            },
            "2": {
                "type": "Company",
                "relevance": "0.265175",
                "text": "IANA" 
            }
        }
    }
}

我的任务是在子文档中搜索“类型”和“文本”,然后按“相关性”排序 . 使用$ elemMatch运算符,我可以执行查询:

db.resource.find({
    'nlp.entities': {
        '$elemMatch': {'text': 'Neelie Kroes', 'type': 'Person'}
    }
});

完美,现在我必须通过相关性降序对“Person”类型的实体和“Neelie Kroes”值进行排序 .

我尝试使用普通的"sort",但是,作为manual said关于$ elemMatch中的sort(),结果可能无法反映排序顺序,因为sort()在$ elemMatch投影之前应用于数组的元素 .

事实上,_id:987456321将是第一个(相关性为0.96,但引用了ICANN) .

如何通过匹配的子文档的相关性对文档进行排序?

P.S . :我无法改变文件结构 .

1 回答

  • 1

    如上所述,我希望您的文档确实有一个数组,但如果$ elemMatch正在为您工作,那么他们应该 .

    无论如何,您无法使用find对数组中的元素进行排序 . 但是有一种情况你可以使用.aggregate()来做到这一点:

    db.collection.aggregate([
    
        // Match the documents that you want, containing the array
        { "$match": {
            "nlp.entities": {
                "$elemMatch": { 
                    "text": "Neelie Kroes", 
                    "type": "Person"   
                }
            }
        }},
    
        // Project to "store" the whole document for later, duplicating the array
        { "$project": {
            "_id": {
                "_id": "$_id",
                "url": "$url",
                "nlp": "$nlp"          
            },
            "entities": "$nlp.entities"
        }},
    
        // Unwind the array to de-normalize
        { "$unwind": "$entities" },
    
        // Match "only" the relevant entities
        { "$match": {
            "entities.text": "Neelie Kroes", 
            "entities.type": "Person"   
        }},
    
        // Sort on the relevance
        { "$sort": { "entities.relevance": -1 } },
    
        // Restore the original document form
        { "$project": {
            "_id": "$_id._id",
            "url": "$_id.url",
            "nlp": "$_id.nlp"
        }}
    ])
    

    基本上,在对包含相关匹配的文档执行$match条件之后,然后使用$project "store" _id 字段中的原始文档和"entities" "entities"数组的"copy" .

    下一个$match "filters"数组内容只包含那些相关的内容 . 然后将$sort应用于"matched"文档 .

    由于"original"文档存储在 _id 下,因此使用$project至"restore"文档实际必须以的结构 .

    这就是你对匹配的数组元素进行“排序”的方法 .

    请注意 if 您在父文档的数组中有多个"matches",然后您必须使用额外的$group阶段来获取"relevance"字段的$ max值才能完成排序 .

相关问题