当前位置:  开发笔记 > 编程语言 > 正文

NoSQL Schemaless数据和静态类型语言

如何解决《NoSQLSchemaless数据和静态类型语言》经验,为你挑选了1个好方法。

像MongoDB这样的NoSQL数据存储的一个主要优点是它们是无模式的.使用动态类型语言,这似乎很自然.您可以接收一些任意JSON输入,在已知字段上执行业务逻辑,并在不必先定义对象的情况下保留整个事物.

如果您选择的语言仅限于静态类型,比如Java,该怎么办?我怎样才能达到同样的灵活性?

典型的数据流如下:

    JSON输入

    Serialize to Java Object以执行业务逻辑

    反序列化为BSON以持续存在于Mongo中

其中序列化到对象步骤是必要的,因为您想要使用POJO而不是JSON字符串执行业务逻辑.但是,在我将输入序列化为对象之前,我必须首先定义它.如果输入包含对象中未定义的其他字段,该怎么办?虽然它们可能不会用于业务逻辑,但我仍然希望能够坚持它们.我似乎已经将未定义的字段放入地图中,但我不确定这是否是最好的方法.首先,未定义的字段也可以是复杂的对象.



1> Michael Dear..:

无架构数据不一定意味着无结构数据; 这些字段通常是预先知道的,并且可以在其上应用一些类型安全的模式以避免Magic Container反模式但是情况并非总是如此.有时键是由用户输入的,并且不能提前知道.

我已经多次使用角色对象模式来使动态结构保持一致.我认为它适用于这两种情况.

角色对象模式定义了访问对象的不同视图的方法.规范示例是可以承担多个角色的用户,例如客户,供应商和卖方.这些视图中的每一个都可以执行不同的操作,并且可以从任何其他视图访问.通用字段通常在接口级别可用(特别是userId()在您的情况下toJson()).

以下是使用该模式的示例:

public void displayPage(User user) {
    display(user.getName());

    if (user.hasView(Customer.class))
       displayShoppingCart(user.getView(Customer.class);

    if (user.hasView(Seller.class))
       displayProducts(user.getView(Seller.class));
}

对于具有已知结构的数据,您可以使用多个视图将不同的键集合转换为内聚单元.这些不同的视图可以读取构造中的json数据.

在具有动态结构的数据的情况下,权威的RawDataView可以使用其动态形式的数据(即,像a 的Magic容器HashMap).这可用于查询动态数据.同时,可以懒惰地创建类型安全的包装器,并且可以委托给RawDataView来协助程序的可读性/可维护性:

 public class Customer implements User {
     private final RawDataView data;
     public CustomerView(UserView source) {
         this.data = source.getView(RawDataView.class);
     }

     // All User views must specify this
     @Override
     public long id() {
         return data.getId();
     }

     @Override
     public  T getView(Class view) {
         // construct or look up view
     }

     @Override
     public Json toJson() {
         return data.toJson();
     }


     //
     // Specific to Customer
     //
     public List shoppingCart() {
         List items = (List) data.getValue("items", List.class); 
     }

     // etc....
 }

我用这两种方法都取得了成功.以下是我在此过程中发现的一些额外指示:

尽可能为您的数据建立静态结构结构.这使事情更容易维护.在处理遗留系统时,我不得不违反此规则并使用RawDataView方法.如上所述,您可能还必须使用动态输入的用户数据来中断它.在这种情况下,对非动态字段名称使用约定,例如前导下划线(_userId)

已经equals()hashcode()实现user.getView(A.class).equals(user.getView(B.class))了对于同一用户始终如此.

有一个UserCore类可以完成所有繁重的公共代码,例如创建视图; 执行常见操作(如toJson())返回公共字段(如userId()); 并实施equals()hashcode().让所有视图委托给这个核心对象

有一个AbstractUserView委托给了UserCore和实现的equals()和hashCode()

使用类型安全的异构容器(如ClassToInstanceMap)构建/缓存视图.

允许查询的存在.这可以通过hasView()方法或getView返回来完成Optional

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有