Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DbRef bug - document is still referenced after delete #831

Closed
Youwannadie opened this issue Dec 12, 2017 · 13 comments
Closed

DbRef bug - document is still referenced after delete #831

Youwannadie opened this issue Dec 12, 2017 · 13 comments

Comments

@Youwannadie
Copy link

Youwannadie commented Dec 12, 2017

Hi,
I think i found bug. If you delete document which is referenced by another document, refference still exists. Db version is 4.0.0. In 3.1.4 it is working properly.
Proof is in attachment
I hope it is clear. Sorry for my english.
dbrefbug

@mbdavid
Copy link
Collaborator

mbdavid commented Dec 12, 2017

Hi @Youwannadie, DbRef has no constraints, like SQL databases. DbRef are only a way to represent document reference. In this case you must manually delete references too.

@Youwannadie
Copy link
Author

I was trying LiteDB Shell with 3.1.4 version and data are same. So difference must be in Include method or something there. If I get data in v4.0.0 referenced documents are populated wrong. In v3.1.4 are populated properly. It means in v3.1.4 must be check or something in Include method and I think it is nice behaviour.

@mbdavid
Copy link
Collaborator

mbdavid commented Dec 13, 2017

Oh, ok. Now I got your point. That's true, this same operation has different returns.

In v3, includes/dbref are used only in LiteDatabase level (after BsonMapper map your class into BsonDocument). Basicly I changed serialize/deserialize methods to include/exclude external class instance. When you add an include in an array, if element are not found they are removed from return (not from collection, only from return).

In v4 this include method are moved into LiteEngine level (before BsonMapper). Now, it's possible include before map into your class. With this, it´s possible do this include in tools that use only BsonDocument, like shell.

db.parent.select $ includes $.Children[*]

But, in both cases (v3/v4) LiteDB doesn't exclude external child. In your example, parent document still has 2 children, one with $id:1 and other with $id:2.

But thinking better about this, I'm still in doubt about this: which version are more correct? When use include operation, remove item if not exists or keeps as $id only?

@Youwannadie
Copy link
Author

Youwannadie commented Dec 13, 2017

For me "remove item if not exists" is right way.
There is not only different result but result in v4 is incorect, Id property has bad value. Please try run my sample code in both versions and spectate "parentFromDb" variable.

class Parent
    {
        public int Id { get; set; }

        public string Name { get; set; }

        [BsonRef("children")]
        public List<Child> Children { get; set; }

        public override string ToString()
        {
            var name = string.IsNullOrEmpty(Name) ? "null" : Name;
            var children = "";
            foreach (var child in Children)
            {
                var childName = string.IsNullOrEmpty(child.Name) ? "null" : child.Name;
                children += $"{child.Id} {childName}, ";
            }
            return $"{Id} {name}\nChildren: {children}";
        }
    }

    class Child
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    class Program
    {
        static string dbName = "db.db";
        static void Main(string[] args)
        {
            if (File.Exists(dbName)) File.Delete(dbName);

            var c1 = new Child { Name = "Klára" };
            var c2 = new Child { Name = "Jakub" };
            var children = new List<Child> { c1, c2 };

            var p = new Parent { Name = "Jakub", Children = children };

            var db = new LiteDatabase(dbName);

            var colChildren = db.GetCollection<Child>("children");
            var colParent = db.GetCollection<Parent>("parents");

            colChildren.InsertBulk(children);
            colParent.Insert(p);

            colChildren.Delete(c1.Id);

            var parentFromDb = colParent.Include(pr => pr.Children).FindOne(pr => true);
            Console.WriteLine(parentFromDb);

            Console.ReadLine();
        }
    }

@Youwannadie
Copy link
Author

Did you try it? @mbdavid

@mbdavid
Copy link
Collaborator

mbdavid commented Dec 19, 2017

Yes, I understand your example and agree that are different from v3.x. But first I will run in MongoDB to check how they implement this case.

The main problem to "remove" is that you are not removing from storage, only removing from viewing results. If I compare with traditional SQL databases with no FK, data also are not removed and join will not return what are expected.

@Youwannadie
Copy link
Author

Thank you, but my main point now is in v4 are children totally wrong. They contains not existing childs.
v3 children: [{2,"Jakub"}] expected: same
v4 children: [{0,null},{1,null}] expected: [{1,null},{2,"Jakub"}]
Child with Id 0 never exists and child with Id 1 was deleted and child with Id 2 is where? Im confused with that behaviour.

@mbdavid
Copy link
Collaborator

mbdavid commented Dec 19, 2017

Hi @Youwannadie, i got it.... in BsonMapper I had this little tricky when deserialize array:

var hasIdRef = array[0].AsDocument == null || array[0].AsDocument["$id"].IsNull;

This line check just first line in array to know if all element are included or only ref. If you mix results, we have a problem. Fix this is easy, but i'm thinking that you right: when use include, must remove from result missing object. To do this, is quite more complicate because I need remove in BsonDocument level and for now, I do not have "remove" method from an BsonExpression. I'm will work on this..

@Youwannadie
Copy link
Author

Nice, thank you.

@mbdavid
Copy link
Collaborator

mbdavid commented Dec 19, 2017

First deserialize problem fixed. But i'm still missing "remove" not found includes....

@mbdavid
Copy link
Collaborator

mbdavid commented Dec 19, 2017

Hi @Youwannadie, can you test now using master branch version? I will add more performance tests and if ok, will release as a bugfix in 4.1.1

@Youwannadie
Copy link
Author

I got same result as in v3.x. So I think it is fixed. :)

@lbnascimento
Copy link
Contributor

Hi! With the objective of organizing our issues, we are closing old unsolved issues. Please check the latest version of LiteDB and open a new issue if your problem/question/suggestion still applies. Thanks!

github-actions bot pushed a commit to Reddevildragg-UPM-Forks/LiteDB that referenced this issue Nov 18, 2020
github-actions bot pushed a commit to Reddevildragg-UPM-Forks/LiteDB that referenced this issue Nov 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants