Watch keynotes and sessions from MongoDB.live, our virtual developer conference.

Average function calculation is incorrect or filtering failure

Need another set of eyes on this one.

The issue is we are intermittently getting incorrect averages using the Swift .average function on a List. We believe the results returned from a filter are what’s causing the .average function to be incorrect based on the number of returned results from the filter

There are three objects in the items List, and then what Realm says is the average of the ‘value’ property. The properties are transaction_id, transaction_name, account, and value. There’s a simple loop in the ItemClass that prints it’s transactions when the GetAverageValue function is called which also prints the average calculated by Realm.

As you can see, the three values are 10, 20 and 30 and the average is 20, but realm is showing 15.0

AC8AABC6-C053-41B1-AD13-0C031B7766F2 Transaction 0 Account 0 10.0
69E9CC4A-2A3A-4437-9A7A-C6EEAA5899BD Transaction 1 Account 0 20.0
D13E6164-E346-4A39-A561-6A780185025B Transaction 2 Account 0 30.0
Average: 15.0

There are three Realm objects, AccountClass, TransactionClass and ItemClass. There’s one account with an id of 1 and one item with a name Item 0.

class AccountClass: Object {
    @objc dynamic var account_id = 0
    @objc dynamic var account_name = ""
    
    let transactionList = List<TransactionClass>()
    override static func primaryKey() -> String {
        return "account_id"
    }
}

class TransactionClass: Object {
    @objc dynamic var transaction_id = UUID().uuidString
    @objc dynamic var transaction_name = ""
    @objc dynamic var account: AccountClass!
    @objc dynamic var _amount = 0.0

    override static func primaryKey() -> String {
        return "transaction_id"
    }
}

class ItemClass: Object {
    @objc dynamic var item_id = UUID().uuidString
    @objc dynamic var item_name = ""

    let transactions = List<TransactionClass>()
    
    func getAverageValue() -> Double {
        self.transactions.forEach { trans in
            let id = trans.transaction_id
            let acct = trans.account.account_name
            let name = trans.transaction_name
            let amt = trans.amount
            print(id, name, acct, amt)
        }
    
        let avgValue: Double = self.transactions.filter("account.account_id == 1").average(ofProperty: "_amount") ?? 0.0
        return avgValue
    }
   
    override static func primaryKey() -> String {
        return "item_id"
    }
}

and then a simple function that creates three transactions and adds them to the existing item

func avgTest() {
   let realm = try! Realm
   let i0 = realm.objects(ItemClass.self).filter("item_name == 'Item 0'").first!
   let account = realm.object(ofType: AccountClass.self, forPrimaryKey: 1)
            
   let t0 = TransactionClass()
   t0.transaction_name = "Transaction 0"
   t0.account = account
   t0.amount = 10.0
            
   let t1 = TransactionClass()
   t1.transaction_name = "Transaction 1"
   t1.account = account
   t1.amount = 20.0
            
   let t2 = TransactionClass()
   t2.transaction_name = "Transaction 2"
   t2.account = account
   t2.amount = 30.0
            
   let a = [t0, t1, t2]    
   try! realm.write {
       i0.transactions.append(objectsIn: a)
   }
            
   let avg = i0.getAverageValue()
   print(avg)
}

note that even if this let avg = i0.getAverageValue() is called outside that function, the results is the same; 15.0

A bit more info.

Note that within the getAverageValue function, it filters where “account.account_id == 1” and it appears that filter is failing on an intermittent basis which is causing the average function to not calculate correctly.

I changed the code to print out the filtered results, and then print the average. Sometimes finds two results, sometimes 3 and sometimes just 1. I ran the test several times, deleting ALL the Realm files and creating the data fresh each time and then in a separate button in the UI, called the getAverageValue function

Run 1
A1E1DC70-7CFB-46CA-8D93-71EE9B3600A1 Transaction 0 10.0
D91F2AFE-3BEC-4B2E-BE5E-212AED0794F2 Transaction 2 30.0
20.0

Run 2
AE8E587B-F137-4351-BF7F-27F130073E18 Transaction 0 10.0
9D7A1C56-E47F-41E5-8881-A8CA7273AF25 Transaction 1 20.0
15.0

Run 3
242A7F57-5546-45F5-9905-D5A759BB2F5A Transaction 0 10.0
10.0

Hi Jay,

I noticed you’ve posted this to a few channels including GitHub: realm-cocoa/issues/6540. To avoid duplicating effort, it would be best to keep the investigation focused on GitHub for this potential bug.

Thanks for the detailed report!

Regards,
Stennie

Hi @Stennie

Thanks for the input.

Just FYI, we were told very specifically in the past to post on the forums first to get more eyes on it in case it was something we were doing (along with a potential SO post).

If no response or resolution for a duplicatable issue, then to open a ticket on the support site, which I did.

I was recently told by Ian the support forums are being depreciated and to open a ticket on Github, so now I’ve done that. I also closed the ticket on the support site.

Sorry for the duplication but we are following directions from your team - I know there are changes so we’re just trying to adapt as we move forward. Perhaps a forum post that defines a clear escalation path for issues would be in order?

Note that I closed the ticket on the support site #6213 and Wes responded. I’ve closed it three times now so not sure why it’s remained open.

Would you like me to delete the forum post, or possibly shorten it and point to the github report?

@Jay The forums will always be open. I said in my email that Realm’s Freshdesk implementation will be closed and merged with MongoDB’s support system - which we are excited about. The support system is for paid support of Realm’s sync product - in the same way it is for MongoDB.

But for any bug type issue that is for the local database without sync, such as this, I would always recommend filing an issue on Github.

1 Like

Hi Jay,

Apologies for confusion on any redirection between channels.

As a quick guide:

  • Community forums are the recommended starting point for discussion on development or product questions if you do not have a paid support plan. There is no SLA (or guarantee) around responses, but anyone in the community is encouraged to share suggestions or experience so you should get more eyes on your posts. Our engineering and product teams also look for community discussions where we can help, but have to balance availability with development and product priorities.

  • If you are using Realm Cloud Standard ($30/month with Community Support), operational questions about Realm Cloud should go to Realm Support. Development and product questions should be posted in community forums.

  • If you have a paid support plan, you will be onboarded to the MongoDB Support Portal. Our Support Portal is fully integrated with our global support team processes, SLAs, and 24x7 coverage. Paid support plans generally cover development, product, and operational questions about MongoDB products & services. The community forums can still be complementary for questions where you want to get input from a broader audience or perhaps on third party frameworks or tools that are not covered by MongoDB support.

  • You can also raise bug reports directly in the relevant project in the Realm GitHub org. If you’re not sure if something is a bug (or your question is around usage), the community forums would be a better place to start.

Raising an issue in multiple channels can split the discussion and duplicate effort. If you do raise an issue in another public channel, it would be excellent to mention the cross-post so other users can follow the discussion.

It’s fine to leave the topic here, since it can act as a signpost to the GitHub issue you posted.

Regards,
Stennie

@Ian_Ward

My apologies… My above post stated you said the support forums were being depreciated and that was a typo on my part.

For clarity, it’s the support portal that’s being depreciated and closed soon

That’s the site at support.realm.io

Jay