具有复杂数据库的Android应用程序的结构

具有复杂数据库的Android应用程序的结构,android,node.js,mongodb,android-volley,android-syncadapter,Android,Node.js,Mongodb,Android Volley,Android Syncadapter,这是我关于StackOverflow的第一个问题:p。我希望它足够具体 下面是项目的结构 RESTAPI是使用NodeJS和MongoDB(mongoose已用于对数据库模式进行建模)以及Express服务器构建的 安卓应用 使用AngularJS的Web应用程序 我的问题是,我应该如何构建Android应用程序和RESTAPI之间的数据同步。以下几点使整个场景更加清晰: 数据库模型(在服务器上)非常复杂,每个数据库模型都有多个子文档 大约有6-7个模型相互参照 我目前正在使用截取从远程服务器

这是我关于StackOverflow的第一个问题:p。我希望它足够具体

下面是项目的结构

  • RESTAPI是使用NodeJS和MongoDB(mongoose已用于对数据库模式进行建模)以及Express服务器构建的
  • 安卓应用
  • 使用AngularJS的Web应用程序
  • 我的问题是,我应该如何构建Android应用程序和RESTAPI之间的数据同步。以下几点使整个场景更加清晰:

    • 数据库模型(在服务器上)非常复杂,每个数据库模型都有多个子文档
    • 大约有6-7个模型相互参照
    • 我目前正在使用截取从远程服务器获取数据
    • 我还考虑添加一个SyncAdapter来定期同步数据,但不确定如何将其与本地数据库合并。我应该为数据库中的每个表/模型使用不同的ContentProvider吗?我应该如何在本地处理嵌套模式(位于远程服务器中)?
    总结我的问题,我想知道的是,考虑到每天大约100000个用户,每个用户每天大约有15-20个请求,最好的方法是-

  • 使用截击来完成我所有的数据库工作
  • 使用本地数据库(SQLite)和SyncAdapter自动保持数据同步?如果是这种情况,您可以推荐一些资源来更好地理解如何将复杂数据库与SyncAdapter集成
  • 您对构建此应用程序的其他建议。
  • 要演示应用程序的复杂性,请查看以下模型

    这是用户模型

    var AddressSchema = new Schema({
        name: String,
        address: String,
        mobile: String,
        pincode: String,
        city: String,
        state: String
    });
    
    var CartSchema = new Schema({
        book: { type: Schema.Types.ObjectId, ref: 'Book' },
        quantity: {
            type: Number,
            default: 1
        },
        dateAdded: Date
    });
    
    var WishlistSchema = new Schema({
        book: { type: Schema.Types.ObjectId, ref: 'Book' },
        dateAdded: Date
    });
    
    var OrderSchema = new Schema({
        orderNumber: String,
        cart: [CartSchema],
        totalAmount: Number,
        deliveryCharge: Number,
        discountAmount: Number,
        address: [AddressSchema],
        date: Date,
        deliveryDate: Date,
        deliveryStatus: String
    });
    
    var SellOrderSchema = new Schema({
        orderNumber: String,
        bookDetails: [{
            isbn: String,
            title: String,
            quantity: {
                type: Number,
                default: 1
            }
        }],
        address: [AddressSchema],
        date: {
            type: Date,
            default: Date.now()
        }
    });
    
    var ReceivedOrdersSchema = new Schema({
        orderNumber: String,
        bookDetails: [{
            book: { type: Schema.Types.ObjectId, ref: 'Book' },
            quantity: Number,
            price: Number
        }],
        dueDate: Date,
        status: {
            type: String,
            default: 'Pending'
        }
    });
    
    var CouponSchema = new Schema({
        coupon: [{ type: Schema.Types.ObjectId, ref: 'Coupon' }],
        used: Number,
        totalDiscount: Number
    });
    
    var UserSchema = new Schema({
        name: String,
        email: { type: String, lowercase: true },
        role: {
            type: String,
            default: 'user'
        },
        hashedPassword: String,
        provider: String,
        salt: String,
        facebook: {},
        twitter: {},
        google: {},
        github: {},
        usedCoupons: [CouponSchema],
        cart: [CartSchema],
        wishlist: [WishlistSchema],
        orders: [OrderSchema],
        sellOrders: [SellOrderSchema],
        addresses: [AddressSchema],
        booksToSell: [{ type: Schema.Types.ObjectId, ref: 'Book' }],
        receivedOrders: [ReceivedOrdersSchema]
    });
    
    这是图书模型

    var BookSchema = new Schema({
      _creator : {type: Schema.Types.ObjectId, ref: 'User'},
      title: String,
      subtitle: String,
      author: String,
      language: String,
      pages: Number,
      publisher: String,
      publishedDate: String,
      isbn10: String,
      isbn13: String, 
      description: String,
      dimensions: {
        height: String,
        width: String,
        thickness: String
      },
      category: String,
      rating: String,
      bookType: String,
      imageLinks: {
        extraLarge: String,
        large: String,
        medium: String,
        small: String,
        smallThumbnail: String,
        thumbnail: String,
        uploaded: String   
      },
      uploadedImageLink: String,
      supplierData: {
        mrp: Number,
        supplierPrice: Number,
        quantity: Number
      },
      pricing: {
        salesPrice: Number,
        deliveryCharge: Number
      },
      dateAdded: Date,
      isFeatured: Boolean,
      isBestseller: Boolean
    });
    

    有5-6个其他此类模型相互依赖

    静态数据

    像UserTable这样的数据大多是静态的,所以可以将其存储在SQLite(甚至是共享首选项)中,以便快速访问本地数据。此外,关于书籍的存储数据(标题、作者等)几乎是静态的(我认为作者不会经常更改),因此将其缓存在SQLite中是简单而直接的

    动态数据

    缓存动态数据?很难,没用,但如果你必须使用截击,它会帮你很多。Volley使用HTTP标记(如
    Expire
    Last Modified
    )缓存您的响应。如果修改了包含时间戳的标记,您的应用程序将发送一个带有
    的HTTP请求。如果来自服务器的数据在该时间戳之后发生了更改,您将收到正常响应。否则,您将收到一个
    http304 Not Modified
    ,您可以使用旧的缓存数据。在这两种情况下,您的应用程序将保存当前时间戳,并在下次使用该时间戳。所有这些都是通过截击来处理的,对你来说是隐藏的,但是知道这些是有用的。您必须弄清楚如何在服务器端处理此问题。如果您不想让服务器处理多个连接,可以先显示用户缓存的数据,并实现一个发送请求的拉入请求手势

    离线访问

    当你的应用程序无法访问互联网时,Volley为你提供了一个抽象层,但你应该为用户添加一个清晰的视觉指示器,让他们知道你向他们展示的东西在此期间可能会发生变化


    总而言之,您应该根据数据的变化频率来划分数据,并根据变化频率采用不同的策略。如果您知道,请指定截击的有效期或日期。

    您认为将SyncAdapter与截击一起使用是否明智。其他表非常动态?对于不频繁的请求(在后台,如检查用户书籍列表或“推荐书籍”列表中的更新)使用SyncAdapters,对于运行时请求使用Volley。另外,在使用SyncAdapter时,尝试提出一个大请求,而不是许多小请求。