【问题标题】:Create RavenDB index based on dynamic properties基于动态属性创建 RavenDB 索引
【发布时间】:2019-12-15 23:27:40
【问题描述】:

在 RavenDB 4.2 中,我想创建一个基于动态对象的索引/映射。最好放在编译时未知的动态属性上。

这是我正在摄取的原始 JSON 的示例:

{
    "id": "A",
    "detections": 
    [
        {
            "steps": [
                {
                    "object": {
                        "id": "A1",
                        "target": {
                            "domain_name": "foobar.com" 
                        }
                    },
                    "object": {
                        "id": "A2",
                        "target": {
                            "ipv4": "127.0.0.1"
                        }
                    }
                }
            ]
        }

    ]
}

上述样本是从第 3 方提取的,并存储在 RavenDB 集合中。粗略翻译,以下模型存在挑战:

public class Step
{
    public string Id { get; set; }
    public DateTime When {get; set;}
    public dynamic Object { get; set; } // aware that it's not handy naming
}

这里的泡菜是 object.target.X 属性名称是动态的。它们不能是强类型的,可以是很多东西,例如:domain_name、ipv4、ipv6、dns、shoe_size、hair_colour 等。这就是为什么整个steps.object 被摄取并存储为System.Object 或dynamic 的原因.

我的目标是基本上对每个 object.target 执行 SelectMany() 并提取 属性名称(键)和值。这将使我的 RavenDB 索引如下所示:

public class StepsIndex : AbstractIndexCreationTask<Models.Step, StepsIndex.Result>
{
    public class Result
    {
        public DateTime When { get; set; }
        public string TargetKey { get; set; }
        public string TargetValue { get; set; }
        // ... removed other properties for brevity
    }

    public StepsIndex()
    {
        Map = steps => 
            from block in blocks
            from detection in blocks.Detections
            from step in detection.Steps

            select new Result
            {
                // extract property name (key), like 'domain_name'
                TargetKey = step.Object.target.GetType().GetProperties()[0].Name,

                // extract property value, like 'foobar.com'
                TargetValue = step.Object.target.GetType().GetProperty(s.Object.target.GetType().GetProperties()[0].Name).GetValue(s.Object.target, null)
            };
    }
}

很遗憾,这不起作用,因为 step.Object 是动态的并在编译时导致以下错误:

错误 [CS1963] 表达式树可能不包含动态操作

我尝试的第二个选项是将其转换为表达式中的 JSON,这也失败了,因为 Raven 的投影在运行时不知道 Newtonsoft.Json:

// Error CS0103: The name 'JObject' does not exist in the current context
// Error CS0103: The name 'JsonConvert' does not exist in the current context
TargetKey = JObject.Parse(JsonConvert.SerializeObject(ass.Object))["target"][0].Value<string>(),

我想到的第三个选项可能是将dynamic Object 更改为System.Object Object,但还没有找到一种在不知道属性的情况下提取属性键/值的简洁方法。

问题:如何提取这些动态属性键和值并将它们映射到 RavenDB 索引?

【问题讨论】:

    标签: c# dynamic reflection mapreduce ravendb


    【解决方案1】:

    【讨论】:

    • 感谢您的参考!不幸的是,我看不到如何通过这个动态提取属性名称(键)和值?引用的文档基于一个模型,在该模型中,无论是在查询还是索引期间,您都会知道要查询哪些字段(键),对吧?
    • 索引时不需要知道字段。
    • 不确定我是否关注。你能用一个简短的例子详细说明如何解决这个问题吗?具体来说,如何映射target.X => 不知道 X 可能是什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多