delete(tx, branch, rows) {
        const { batchToken, withMutations } = tx;

        const { arrName, mapName } = this;
        const arr = branch[arrName];

        const idsToDelete = rows.map((row) => row[this.idAttribute]);
        if (withMutations) {
            idsToDelete.forEach((id) => {
                const idx = arr.indexOf(id);
                ops.mutable.splice(idx, 1, [], arr);
                ops.mutable.omit(id, branch[mapName]);
            });
            // delete ids from all indexes
            Object.values(branch.indexes).forEach((attrIndex) =>
                Object.values(attrIndex).forEach((valueIndex) =>
                    idsToDelete.forEach((id) => {
                        const idx = valueIndex.indexOf(id);
                        if (idx !== -1) {
                            ops.mutable.splice(idx, 1, [], valueIndex);
                        }
                    })
                )
            );
            return branch;
        }

        const nextIndexes = ops.batch.merge(
            batchToken,
            Object.entries(branch.indexes).reduce(
                (indexMap, [attr, attrIndex]) => {
                    indexMap[attr] = ops.batch.merge(
                        batchToken,
                        Object.entries(attrIndex).reduce(
                            (attrIndexMap, [value, valueIndex]) => {
                                attrIndexMap[value] = ops.batch.filter(
                                    batchToken,
                                    (id) => !idsToDelete.includes(id),
                                    valueIndex
                                );
                                return attrIndexMap;
                            },
                            { ...indexMap[attr] }
                        ),
                        indexMap[attr]
                    );
                    return indexMap;
                },
                { ...branch.indexes }
            ),
            branch.indexes
        );

        return ops.batch.merge(
            batchToken,
            {
                [arrName]: ops.batch.filter(
                    batchToken,
                    (id) => !idsToDelete.includes(id),
                    branch[arrName]
                ),
                [mapName]: ops.batch.omit(
                    batchToken,
                    idsToDelete,
                    branch[mapName]
                ),
                indexes: ops.batch.merge(
                    batchToken,
                    nextIndexes,
                    branch.indexes
                ),
            },
            branch
        );
    }
Returns the data structure without rows `rows`.
@param  {Object} tx - transaction info
@param  {Object} branch - the data structure state
@param  {Object[]} rows - rows to update
@return {Object} the data structure without ids in `idsToDelete`.