C# RavenDB索引:需要一个解决方案将两个字典字段合并到一个字典中,将其展平并使其可搜索

C# RavenDB索引:需要一个解决方案将两个字典字段合并到一个字典中,将其展平并使其可搜索,c#,ravendb,C#,Ravendb,我们正在为一个客户构建一个嵌套的UI视图,需要一个解决方案来将两个字典字段合并到一个统一的字典中,并使键可以像字段名一样进行搜索。我使用和中提到的技术创建了一个Map/Reduce索引 NameProperties–它是已知键、值对的字典。例如 "NamedProperties": [ { "Key": "Tags", "Value": "" }, { "Key": "Name", "Value": "file-184"

我们正在为一个客户构建一个嵌套的UI视图,需要一个解决方案来将两个字典字段合并到一个统一的字典中,并使键可以像字段名一样进行搜索。我使用和中提到的技术创建了一个Map/Reduce索引

NameProperties–它是已知键、值对的字典。例如

"NamedProperties": [
    {
      "Key": "Tags",
      "Value": ""
    },
    {
      "Key": "Name",
      "Value": "file-184"
    },
    {
      "Key": "Uploader",
      "Value": "rmani@transper.com"
    },
    {
      "Key": "FileType",
      "Value": "Jpg"
    },
    {
      "Key": "Language",
      "Value": "English"
    }]
属性–它是一个合并字典,包含MetadataProperties和NamedProperties中的键、值对

扁平属性和u是分别包含“NamedProperties”和“MetadataProperties”扁平字段值的属性。我想不出一种方法来展平计算属性,比如结合了MetadataProperties和NamedProperties字典的“Properties”。我试过海螺

以下是索引创建代码:

public class PortalEntryViews_DocumentIdSplitIndex : AbstractIndexCreationTask<PortalEntry, ViewFolderResultWithIndividualProperties>
        {
            public PortalEntryViews_DocumentIdSplitIndex()
            {
                Map = portalEntries => from portalEntry in portalEntries
                                       select new 
                                                     {
                                                         EntryId = portalEntry.Id,
                                                         MetadataProperties = portalEntry.MetaData.Select(t => new KeyValuePair<string, string>(t.Key, t.Value)).ToList(),                                                         
                                                         NamedProperties = new List<KeyValuePair<string, string>> { 
                                                             new KeyValuePair<string, string>("Tags", string.Join(",", portalEntry.Tags.Where(t => !t.IsInternal).Select(t=>t.Name))),
                                                             new KeyValuePair<string, string>("Name", portalEntry.Name),
                                                             new KeyValuePair<string, string>("Uploader", portalEntry.Uploader),
                                                             new KeyValuePair<string, string>("FileType", portalEntry.FileType),
                                                             new KeyValuePair<string, string>("Language", portalEntry.Language),
                                                             new KeyValuePair<string, string>("Name", portalEntry.Name) },
                                                             Properties = new List<KeyValuePair<string, string>>(),
                                                             FlattenedProperties = "",
                                                         _ = ""                                                         
                                                     };


                Reduce = results => from result in results                                    
                                    group result by new { result.EntryId, result.MetadataProperties, result.NamedProperties, result.FlattenedProperties, result._ } into g
                                    select new
                                    {
                                        EntryId = g.Key.EntryId,
                                        MetadataProperties = g.Key.MetadataProperties,
                                        NamedProperties = g.Key.NamedProperties,
                                        Properties = g.Key.MetadataProperties.Concat(g.Key.NamedProperties).ToList(),
                                        FlattenedProperties = g.Key.NamedProperties.Select(f => CreateField(f.Key, f.Value)),
                                        _ = g.Key.MetadataProperties.Select(t => CreateField(t.Key, t.Value, true, true))
                                    };


            }
        }
我的最终目标是使用CreateField将组合字典(即Properties字段)扁平化为单个字段,可以使用键进行搜索,就好像它们是字段名一样。但是,如果我用这样的电话:

Properties=g.Key.MetadataProperties.Concatg.Key.NamedProperties.ToList.Selectt=>CreateFieldt.Key,t.Value,true,true,它似乎在运行,但当您从Ravendb Explorer查看索引时,它显示了实际错误:

阶段:索引部分:减少说明:“System.Collections.Generic.List”不包含“Select”的定义

现在,我只能将一个Dictionary MetadataProperties展平到reduce部分的“\u1”字段中,该字段可以从Ravendb Explorer和使用LuceneQuery的C代码中使用,但这不符合我的要求


有人能帮我解决这个问题吗?

如果你只想搜索键值,你可以做得很简单

//the index
public class FlattenIndex: AbstractIndexCreationTask<PortalEntry>
    {
        public class ReduceResult
        {
            public string Key { get; set; }
            public string Value { get; set; }
        }
        public FlattenIndex()
        {
            Map = portalEntries => from portalEntry in portalEntries                                                               
                                   from p in portalEntry.MetadataProperties.Concat(portalEntry.NamedProperties)
                           select new
                           {
                               Key=p.Key,
                               Value=p.Value
                           };
        }
    }

//the query
 using (var session = _docStore.OpenSession())
            {
                var someEntries = session.Query<FlattenIndex.ReduceResult, FlattenIndex>()
                    .Where(x => x.Key == "Language" && x.Value == "English")
                    .As<PortalEntry>()
                    .ToArray();
                if (someEntries!=null)
                    foreach(var entry in someEntries )
                    {
                        Console.WriteLine(entry.Id);
                    }
            }
public class PortalEntryViews_DocumentIdSplitIndex : AbstractIndexCreationTask<PortalEntry, ViewFolderResultWithIndividualProperties>
        {
            public PortalEntryViews_DocumentIdSplitIndex()
            {
                Map = portalEntries => from portalEntry in portalEntries
                                       select new 
                                                     {
                                                         EntryId = portalEntry.Id,
                                                         MetadataProperties = portalEntry.MetaData.Select(t => new KeyValuePair<string, string>(t.Key, t.Value)).ToList(),                                                         
                                                         NamedProperties = new List<KeyValuePair<string, string>> { 
                                                             new KeyValuePair<string, string>("Tags", string.Join(",", portalEntry.Tags.Where(t => !t.IsInternal).Select(t=>t.Name))),
                                                             new KeyValuePair<string, string>("Name", portalEntry.Name),
                                                             new KeyValuePair<string, string>("Uploader", portalEntry.Uploader),
                                                             new KeyValuePair<string, string>("FileType", portalEntry.FileType),
                                                             new KeyValuePair<string, string>("Language", portalEntry.Language),
                                                             new KeyValuePair<string, string>("Name", portalEntry.Name) },
                                                             Properties = new List<KeyValuePair<string, string>>(),
                                                             FlattenedProperties = "",
                                                         _ = ""                                                         
                                                     };


                Reduce = results => from result in results                                    
                                    group result by new { result.EntryId, result.MetadataProperties, result.NamedProperties, result.FlattenedProperties, result._ } into g
                                    select new
                                    {
                                        EntryId = g.Key.EntryId,
                                        MetadataProperties = g.Key.MetadataProperties,
                                        NamedProperties = g.Key.NamedProperties,
                                        Properties = g.Key.MetadataProperties.Concat(g.Key.NamedProperties).ToList(),
                                        FlattenedProperties = g.Key.NamedProperties.Select(f => CreateField(f.Key, f.Value)),
                                        _ = g.Key.MetadataProperties.Select(t => CreateField(t.Key, t.Value, true, true))
                                    };


            }
        }
var entries =
                    session.Advanced.LuceneQuery<ViewFolderResultWithIndividualProperties>(
                        "PortalEntryViews/DocumentIdSplitIndex")
                        .WhereEquals("Language", "English").ToList(); 
Raven.Imports.Newtonsoft.Json.JsonSerializationException : Could not read value for property: FlattenedProperties  ----> Raven.Imports.Newtonsoft.Json.JsonReaderException : Error reading string. Unexpected token: StartArray 
//the index
public class FlattenIndex: AbstractIndexCreationTask<PortalEntry>
    {
        public class ReduceResult
        {
            public string Key { get; set; }
            public string Value { get; set; }
        }
        public FlattenIndex()
        {
            Map = portalEntries => from portalEntry in portalEntries                                                               
                                   from p in portalEntry.MetadataProperties.Concat(portalEntry.NamedProperties)
                           select new
                           {
                               Key=p.Key,
                               Value=p.Value
                           };
        }
    }

//the query
 using (var session = _docStore.OpenSession())
            {
                var someEntries = session.Query<FlattenIndex.ReduceResult, FlattenIndex>()
                    .Where(x => x.Key == "Language" && x.Value == "English")
                    .As<PortalEntry>()
                    .ToArray();
                if (someEntries!=null)
                    foreach(var entry in someEntries )
                    {
                        Console.WriteLine(entry.Id);
                    }
            }