12.10.0版本新增。
适用于 Node.js 的Atlas Device SDK提供了一个计数器类,您可以在处理同步数据库时将其用作逻辑计数器。 传统上,您会存储计数器值并手动读取、递增和设立该值。 但是,如果多个客户端尝试更新计数器,则可能导致客户端之间的根本的值不准确。
考虑这样一种情况:某一Realm 对象具有int类型的 count属性。 设备 A 和 B 均将该值读取为0 ,然后通过将1添加到读取的值来增加计数。 根本的值仅为 ,而不是反映两个设备的增量并收敛为21 。
Counter类可以同步这些更新,使所有客户端的值收敛到相同的根本的值。
SDK 的counter是一种表示数据类型,根本的类型为int 。 这意味着将int类型更改为counter时无需迁移。
计数器不能用作:
定义计数器属性
要使用Counter类,请将Realm对象中的一个属性声明为类型Counter 。
您可以选择将此属性声明为可空,方法是使其为可选并将Counter和null作为类型传递。 对于可空计数器,您可以根据需要将Realm对象中的计数器属性设立为null 。
该属性使用以下任一方法进行初始化:
对象表示法
{ type: "int", presentation: "counter" }{ type: "int", presentation: "counter", optional: true }
速记
"counter""counter?"
export class ClassWithCounter extends Realm.Object { static schema = { name: "ClassWithCounter", primaryKey: "_id", properties: { _id: { type: "objectId", default: () => new BSON.ObjectId() }, myCounter: { type: "int", presentation: "counter" }, // or myCounter: "counter" nullableCounter: { type: "int", presentation: "counter", optional: true }, // or nullableCounter: "counter?" }, }; }
export class ClassWithCounter extends Realm.Object<ClassWithCounter> { _id!: BSON.ObjectId; myCounter!: Counter; nullableCounter?: Counter | null; static schema: ObjectSchema = { name: "ClassWithCounter", primaryKey: "_id", properties: { _id: { type: "objectId", default: () => new BSON.ObjectId() }, myCounter: { type: "int", presentation: "counter" }, // or myCounter: "counter" nullableCounter: { type: "int", presentation: "counter", optional: true }, // or nullableCounter: "counter?" }, }; }
创建和更新计数器
要初始化计数器,请使用realm.create()方法创建对象。 传入您的Realm对象模式和初始计数器值,以及该对象具有的任何其他属性的初始值。
const siteVisitTracker = realm.write(() => { return realm.create(SiteVisitTracker, { siteVisits: 0 }); });
然后,您可以使用以下方法修改计数器值:
increment()和decrement()将根本的值更新指定的数字。set()将计数器重新分配为指定值。
siteVisitTracker.siteVisits.increment(); siteVisitTracker.siteVisits.value; // 1 siteVisitTracker.siteVisits.increment(2); siteVisitTracker.siteVisits.value; // 3 siteVisitTracker.siteVisits.decrement(2); siteVisitTracker.siteVisits.value; // 1 siteVisitTracker.siteVisits.increment(-2); siteVisitTracker.siteVisits.value; // -1 siteVisitTracker.siteVisits.set(0); // reset counter value to 0
警告
计数器重置
使用set()时要小心,因为它会覆盖之前对increment()和decrement()的任何调用。 根据操作顺序,这可能会导致计数器收敛到不同的值。 为避免客户端的计数器值不准确,我们建议您避免将set()与increment()和decrement()混合使用。
要将可空计数器更新为null 值或从值更新,您必须使用realm.create()并指定UpdateMode 。 这不会更新根本的计数器值,而是将计数器属性设置为 null 或新计数器。
UpdateMode 根据指定的模式,更新具有匹配主键的任何现有计数器对象:
UpdateMode.All更新提供的所有属性。UpdateMode.Modified仅更新已修改的属性。
const siteVisitTracker = realm.write(() => { return realm.create(SiteVisitTracker, { nullableSiteVisits: 0, siteVisits: 1, }); }); const myID = siteVisitTracker._id; realm.write(() => { realm.create( SiteVisitTracker, { _id: myID, nullableSiteVisits: null }, UpdateMode.Modified ); }); realm.write(() => { realm.create( SiteVisitTracker, { _id: myID, nullableSiteVisits: 0 }, UpdateMode.Modified ); });
查询计数器值
您可以像查询其他属性类型一样查询计数器属性。 但是,要按根本的计数器值进行查询,您必须在参数化查询中传递counter.value 。 在以下示例中,我们要查找计数器值大于或等于指定计数器值的所有对象。
const belowThreshold = realm.write(() => { return realm.create(SiteVisitTracker, { siteVisits: 0 }); }); const atThreshold = realm.write(() => { return realm.create(SiteVisitTracker, { siteVisits: 1 }); }); const aboveThreshold = realm.write(() => { return realm.create(SiteVisitTracker, { siteVisits: 2 }); }); const allObjects = realm.objects("SiteVisitTracker"); let filteredObjects = allObjects.filtered( "siteVisits >= $0", atThreshold.siteVisits.value );
有关使用 SDK 进行查询的更多信息,请参阅RQL 。