vadimtsushko / objectory

Unsupported: Objectory - object document mapper for server-side and client side Dart applications
MIT License
55 stars 12 forks source link

Unable to query results unless I drop the collection. #61

Closed delaneyj closed 10 years ago

delaneyj commented 10 years ago

Took a project I'm working on and convert the core to a single file console program to show the issue. Basically if I follow the examples and drop the tables and fill with fresh data I am able to query properly. However if I run the same query on a db after that with a new connection I'm getting null values.

import 'package:objectory/objectory_console.dart';

void main() {
  String uri = 'mongodb://127.0.0.1/test';

  Completer completer = new Completer();
  objectory = new ObjectoryDirectConnectionImpl(uri,registerClasses,true);
  objectory.initDomainModel().then((_){
    initCollections();

    objectory[PurchaseModel].findOne().then((PurchaseModel pm){
      print("If I drop the tables I get the proper value.");
      print(pm.buyer.name);
      objectory.close();
      completer.complete();
    });
  });

  completer.future.then((_){
    objectory = new ObjectoryDirectConnectionImpl(uri,registerClasses,false);
    objectory.initDomainModel().then((_){
      print("Mongo should already have models");

      objectory[PurchaseModel].findOne().then((PurchaseModel pm){
        print("If I don't drop the tables and initCollections again it appears that the same query fails.");
        print(pm.buyer.name);
        print("Why is this null and what am I doing wrong?");
        objectory.close();
      });
    });
  });
}

void registerClasses(){
  objectory.registerClass(AssetModel,()=>new AssetModel(),()=>new List<AssetModel>());
  objectory.registerClass(UserModel,()=>new UserModel(),()=>new List<UserModel>());
  objectory.registerClass(PurchaseModel,()=>new PurchaseModel(),()=>new List<PurchaseModel>());
}

initCollections() {
  UserModel buyer = new UserModel()
    ..name = "I'm a buyer";

  UserModel creator = new UserModel()
    ..name = "I'm an author";

  Future.wait([buyer.save(),creator.save()]);

  AssetModel product1 = new AssetModel()
    ..author = creator
    ..name = "An asset"
    ..lastUpdated = new DateTime(2013, 1, 2, 3, 4, 5);

  Future.wait([product1.save()]);

  PurchaseModel purchase =  PurchaseModel.create(buyer,product1);
  Future.wait([purchase.save()]);
}

class UserModel extends PersistentObject {
  String get name => getProperty('name');
  set name(String value) => setProperty('name',value);
}

class AssetModel extends PersistentObject {
  String get name => getProperty('name');
  set name(String value) => setProperty('name',value);

  DateTime get lastUpdated => getProperty('lastUpdated');
  set lastUpdated (DateTime value) => setProperty('lastUpdated',value);

  UserModel get author => getLinkedObject('author');
  set author (UserModel value) => setLinkedObject('author',value);
}

class PurchaseModel extends PersistentObject{
  UserModel get buyer  => getLinkedObject('buyer');
  set buyer(UserModel value) => setLinkedObject('buyer',value);

  AssetModel get asset => getLinkedObject('asset');
  set asset(AssetModel value) => setLinkedObject('asset',value);

  DateTime get time => getProperty('time');
  set time(DateTime value) => setProperty('time',value);

  static PurchaseModel create(UserModel buyer, AssetModel asset) {
    var purchase = new PurchaseModel()
      ..buyer = buyer
      ..asset = asset
      ..time = new DateTime.now();
    return purchase;
  }
}
vadimtsushko commented 10 years ago

While querying DB Objectory do not follow all links automatically. Otherwise retrieving one object from db you potentially may get all db (by transitive links). Instead you get object with pointers to linked object. To populate these pointers with real objects you may use fetchLinks method of original persistent object.

See console blog example:

Future printArticle(article) {
  var completer = new Completer();
  article.fetchLinks().then((__) {
    print("${article.author.name}:${article.title}:${article.body}");
    for (var comment in article.comments) {
      print("     ${comment.date}:${comment.user.name}: ${comment.body}");
    }
    completer.complete(true);
  });
  return completer.future;
}

Or you may set queryBuilder to fetch links for you on query. In your example that would be:

objectory[PurchaseModel].findOne(where.fetchLinks()).then((PurchaseModel pm){
delaneyj commented 10 years ago

Is there a more proper way for me to do this? In my example I'm just trying to grab the user's name. I'd think something like pm.buyer.fetch().then((UserModel u){}); would be the efficient way to do this.

When I tried that it looks like persistent_object.dart Line188 is returning true instead of the actual PersistentObject. Am I understanding this incorrectly?

vadimtsushko commented 10 years ago

Both

objectory[PurchaseModel].findOne(where.fetchLinks()).then((PurchaseModel pm){
    print("If I don't drop the tables and initCollections again it appears that the same query fails.");
    print(pm.buyer.name);
    print("Why is this null and what am I doing wrong?");
    objectory.close();
});

And

objectory[PurchaseModel].findOne().then((PurchaseModel pm){
  return pm.fetchLinks();
}).then((pm) {
  print("If I don't drop the tables and initCollections again it appears thathe same query fails.");
  print(pm.buyer.name);
  print("Why is this null and what am I doing wrong?");
  objectory.close();
});

work in your example. That are the proper ways.

delaneyj commented 10 years ago

Now that you've explained how it works fetchLinks() brings up concerns in my situation. So I need to avoid setting up models where deep linking is occurring? Is there any way to selectively fetchLinks?

delaneyj commented 10 years ago

Sorry for the confusion, now I think its starting to make sense. In my case another query of objectory[UserModel].findOne(where.id(pm.buyer.id)).then((UserModel u){/*doStuff*/}); will work as I want. Thanks for your time and patience. This conversation could probably be used as the basis for filling in the quick tour on the subject of fetchLinks()

vadimtsushko commented 10 years ago

Thank you for kindly words. I definitely should refresh and extend quick tour. Hope I'll manage to do it soon.