/// <summary>Remove an entity from the index</summary> /// <param name="trans">Transaction to use</param> /// <param name="id">Id of the entity that has been deleted</param> /// <param name="value">Previous value of the entity in the index</param> public async Task <bool> RemoveAsync(IFdbTransaction trans, long id, TValue value) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } var key = this.Subspace[value]; var data = await trans.GetAsync(key).ConfigureAwait(false); if (data.HasValue) { var builder = new CompressedBitmapBuilder(MutableSlice.AsUnsafeMutableSlice(data)); builder.Clear((int)id); //BUGBUG: 64 bit id! trans.Set(key, builder.ToSlice()); return(true); } return(false); }
/// <summary>Returns a list of ids matching a specific value</summary> /// <param name="trans"></param> /// <param name="value">Value to lookup</param> /// <param name="reverse"></param> /// <returns>List of document ids matching this value for this particular index (can be empty if no document matches)</returns> public async Task <IEnumerable <long>?> LookupAsync(IFdbReadOnlyTransaction trans, TValue value, bool reverse = false) { var key = this.Subspace[value]; var data = await trans.GetAsync(key).ConfigureAwait(false); if (data.IsNull) { return(null); } if (data.IsEmpty) { return(Enumerable.Empty <long>()); } var bitmap = new CompressedBitmap(MutableSlice.AsUnsafeMutableSlice(data)); if (reverse) { throw new NotImplementedException(); //TODO: GetView(reverse:true) ! } return(bitmap.GetView().Select(x => (long)x /*BUGBUG 64 bits*/)); }
/// <summary>Update the indexed values of an entity</summary> /// <param name="trans">Transaction to use</param> /// <param name="id">Id of the entity that has changed</param> /// <param name="newValue">Previous value of this entity in the index</param> /// <param name="previousValue">New value of this entity in the index</param> /// <returns>True if a change was performed in the index; otherwise false (if <paramref name="previousValue"/> and <paramref name="newValue"/>)</returns> /// <remarks>If <paramref name="newValue"/> and <paramref name="previousValue"/> are identical, then nothing will be done. Otherwise, the old index value will be deleted and the new value will be added</remarks> public async Task <bool> UpdateAsync(IFdbTransaction trans, long id, TValue newValue, TValue previousValue) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (!this.ValueComparer.Equals(newValue, previousValue)) { // remove previous value if (this.IndexNullValues || previousValue != null) { var key = this.Subspace[previousValue]; var data = await trans.GetAsync(key).ConfigureAwait(false); if (data.HasValue) { var builder = new CompressedBitmapBuilder(MutableSlice.AsUnsafeMutableSlice(data)); builder.Clear((int)id); //BUGBUG: 64 bit id! trans.Set(key, builder.ToSlice()); } } // add new value if (this.IndexNullValues || newValue != null) { var key = this.Subspace[newValue]; var data = await trans.GetAsync(key).ConfigureAwait(false); var builder = data.HasValue ? new CompressedBitmapBuilder(MutableSlice.AsUnsafeMutableSlice(data)) : CompressedBitmapBuilder.Empty; builder.Set((int)id); //BUGBUG: 64 bit id! trans.Set(key, builder.ToSlice()); } // cannot be both null, so we did at least something) return(true); } return(false); }
/// <summary>Insert a newly created entity to the index</summary> /// <param name="trans">Transaction to use</param> /// <param name="id">Id of the new entity (that was never indexed before)</param> /// <param name="value">Value of this entity in the index</param> /// <returns>True if a value was inserted into the index; or false if <paramref name="value"/> is null and <see cref="IndexNullValues"/> is false, or if this <paramref name="id"/> was already indexed at this <paramref name="value"/>.</returns> public async Task <bool> AddAsync(IFdbTransaction trans, long id, TValue value) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (this.IndexNullValues || value != null) { var key = this.Subspace[value]; var data = await trans.GetAsync(key).ConfigureAwait(false); var builder = data.HasValue ? new CompressedBitmapBuilder(MutableSlice.AsUnsafeMutableSlice(data)) : CompressedBitmapBuilder.Empty; //TODO: wasteful to crate a builder to only set on bit ? builder.Set((int)id); //BUGBUG: id should be 64-bit! //TODO: if bit was already set, skip the set ? trans.Set(key, builder.ToSlice()); return(true); } return(false); }