使用正则表达式在 mongo 集合中搜索叶子内的字段

Searching a field inside a leaf in a mongo collection with regex

我有以下 mongo 集合,其中的记录见下面的 json 示例记录,它表示 一条 记录。例如,我的目标是搜索单词 "CONST" 并查找 "Aliases" 子树 中的 "FullName" 字段 包含该单词的记录。以显示的记录为例,它应该命中,因为 "Aliases" 树中的叶子 533-1 和 533-2 在其各自的 "FullName" 字段上包含字符串 "CONST"。例如,如果别名树仅包含树内的 533-3 叶,则它不会命中。

我使用 C# 和 MongoDb.Driver 包并使用 Regex 搜索普通字段 - 例如对于显示的此集合中的 "Key",我使用“Builders.Filter.And(filter, Builders.Filter.Regex("Key", new BsonRegularExpression("")))”模式添加条件。但是对于 "Aliases" 子树中的这些字段,我不知道如何添加条件。搜索此字段的最简单方法是什么?

请注意,在 "Aliases" 下,每片叶子都有不同的名称(533-1、533-2 等)。每片叶子的名字在整个馆藏的每条记录中都是唯一的。 记录示例:

{
"_id" : "128c5c57-ae95-4a08-9fb8-d6eade663908",
"_t" : "Company",
"ActiveFrom" : "20190813154343",
"ActiveTo" : "30001001000001",
"GroupId" : "38547478-88ef-4caf-a6ce-1a9e6a85a59b",
"Key" : "533",
"FullName" : "RED BRIGADES",
"Countries" : [ 
    "ITALY"
],
"MoreInfo" : null,
"RecordDetail" : "<RecordDetail></RecordDetail>",
"Aliases" : {
    "533-1" : {
        "Key" : "533-1",
        "FullName" : "BRIGADAS ROJAS PARA LA CONSTRUCCIÓN DEL PARTIDO COMUNISTA COMBATIENTE",
        "OriginalKey" : "533"
    },
    "533-2" : {
        "Key" : "533-2",
        "FullName" : "BRIGADES ROUGES POUR LA CONSTRUCTION DU PARTI COMMUNISTE COMBATTANT",
        "OriginalKey" : "533"
    },
    "533-3" : {
        "Key" : "533-3",
        "FullName" : "BRIGATE ROSSE",
        "OriginalKey" : "533"
    },
    "533-4" : {
        "Key" : "533-4",
        "FullName" : "BRIGATE ROSSE PER LA COSTRUZIONE DEL PARTITO COMUNISTA COMBATTENTE",
        "OriginalKey" : "533"
    }
}

}

以下聚合管道将为您提供所需的结果。我认为尝试在 c# 中构建此管道是不值得的,因为没有 objectToArray 的构建器,而您的情况需要它。如果您的别名叶子是数组项,那么我们可以使用驱动程序的构建器构建管道。也许其他人有更好的方法。让我们看看...

db.companies.aggregate([
{
  $match: {
    $expr: {
      $gt: [
        {
          $size: {
            $filter: {
              input: {
                $objectToArray: "$Aliases"
              },
              as: "alias",
              cond: {
                $regexMatch: {
                  input: "$$alias.v.FullName",
                  regex: /CONST/
                }
              }
            }
          }
        },
        0
      ]
    }
  }
}
])

这可能 运行 比 查询慢,但这是可读的,您可以理解它并优化它。

db.Companies.aggregate([
    // Add temporary field deconstructed_aliases to every document of collection
    {
        $addFields: {
            deconstructed_aliases: {
                $objectToArray: "$Aliases"
            }
        }
    },
    // Unwind this newly created temporary field deconstructed_aliases
    {
        $unwind: "$deconstructed_aliases"
    },
    // Match on fullName now
    {
        $match: {
            "deconstructed_aliases.v.FullName": {
                $regex: new RegExp('CONST', 'i')
            }
        }
    },
    // Project needed fields
    {
        $project: {
            _id: 0,
            key: "$deconstructed_aliases.v.Key",
            fullName: "$deconstructed_aliases.v.FullName"
        }
    }
]);

C# 驱动程序在聚合流畅接口中似乎没有 addField 辅助方法。

此外,没有直接支持规范化对象所需的 objectToArray 运算符,因此创建魔术字符串作为解决方法。

这里有对应的C#程序-

using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Testing
{
    class Program
    {
        static void Main(string[] args)
        {
            MongoClient client = new MongoClient("mongodb://localhost:27017/test");
            IMongoDatabase database = client.GetDatabase("test");
            IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("Companies");

            string searchTerm = "CONST";
            string searchResult = FetchKeysBySearchTerm(collection, searchTerm).Result.ToJson();
            Console.WriteLine(searchResult);
        }

        public async static Task<List<BsonDocument>> FetchKeysBySearchTerm(IMongoCollection<BsonDocument> collection, string searchTerm)
        {
            string addFieldStage = @"{ $addFields: { deconstructed_aliases: { $objectToArray: ""$Aliases"" } } }";
            string unwindStage = @"{ $unwind: ""$deconstructed_aliases"" }";
            string projectStage = @"{ $project: { _id: 0, key: ""$deconstructed_aliases.v.Key"", fullName: ""$deconstructed_aliases.v.FullName"" } }";

            var aggregate = collection.Aggregate()
                                      .AppendStage<BsonDocument>(addFieldStage)
                                      .AppendStage<BsonDocument>(unwindStage)
                                      .Match(Builders<BsonDocument>.Filter.Regex("deconstructed_aliases.v.FullName", new BsonRegularExpression(searchTerm, "i")))
                                      .AppendStage<BsonDocument>(projectStage);


            List<BsonDocument> searchResults = await aggregate.ToListAsync();
            return searchResults;
        }
    }
}

这是示例响应 -

[{ "key" : "533-1", "fullName" : "BRIGADAS ROJAS PARA LA CONSTRUCCIÓN DEL PARTIDO COMUNISTA COMBATIENTE" }, { "key" : "533-2", "fullName" : "BRIGADES ROUGES POUR LA CONSTRUCTION DU PARTI COMMUNISTE COMBATTANT" }]