I tried to fetch the records which are stored in the core data, and I logged the fetch objects with NSLog and they are as below.
<NSManagedObject: 0x4e31920> (entity: MyEntity; id: 0x4e30a80 <x-coredata://01F71B1D-B468-4FCC-B083-8254F375ADE5/MyEntity/p1> ; data: <fault>)
What is the meaning of "data: <fault>" ?
Is the data corrupted ?
Thanks
No. Data is not corrupted. Take a look here for a complete description of what is happening:
Core-Data: NSLog output Does Not Show "Fields"
When fetching the data, you can ask your fetchRequest to respond with data non-faulted by calling
[fetchRequest setReturnObjectsAsFaults:NO];
Here's some more details about faulting:
Faulting
Managed objects typically represent data held in a persistent store. In some situations a managed object may be a “fault”—an object whose property values have not yet been loaded from the external data store—see “Faulting and Uniquing” for more details. When you access persistent property values, the fault “fires” and the data is retrieved from the store automatically. This can be a comparatively expensive process (potentially requiring a round trip to the persistent store), and you may wish to avoid unnecessarily firing a fault (see “Faulting Behavior”).
Although the description method does not cause a fault to fire, if you implement a custom description method that accesses the object’s persistent properties, this will cause a fault to fire. You are strongly discouraged from overriding description in this way.
There is no way to load individual attributes of a managed object on an as-needed basis. For patterns to deal with large attributes, see “Large Data Objects (BLOBs).”
More information can be found here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdManagedObjects.html#//apple_ref/doc/uid/TP40003397-SW2
Related
I am using Sitecore 8.1 with xDB enabled (MongoDB). I would like to store the user-roles of the visiting users in the xDB, so I can aggregate on these data in my reports. These roles can change over time, so one user could have one set of roles at some point in time and another set of roles at a later time.
I could go and store these user-roles as custom facets on the Contact entity, but as they may change for a user from visit to visit, I will loose historical data if I update the data in the facet every time the user log in (fx. I will not be able to tell which roles a given user had, at some given visit).
Instead, I could create a custom IElement for my facet data, and store the roles along with a timestamp saying when the given roles were registered, but this model may be hard to handle during the reporting phase, where I would need to connect the interaction data with the role-data based on timestamps every time I generate a report.
Is it possible to store these custom data in the xDB in something else than the Contact collection? Can I store custom data in the Interactions collection? There is a property called Tracker.Current.Session.Interaction.CustomValues which sounds like what I need, but if I store data here, will I be able to perform proper aggregation/reporting on the data? Any other approaches I haven't thought about?
CustomValues
Yes, the CustomValues dictionary is what I would use in your case. This dictionary will get serialized to MongoDB as a nested document of every interaction (unless the dictionary is empty).
Also note that, since CustomValues is a member of the base class Sitecore.Analytics.Model.Entity, this dictionary is available in many other data classes of xDB. For example, you can store custom values in PageData and PageEventData objects.
Since CustomValues takes an object of any class, your custom data class needs some extra things for it to be successfully saved to and subsequently loaded from MongoDB:
It has to be marked as [Serializable].
It needs to be registered in the MongoDB driver like this:
using Sitecore.Analytics.Data.DataAccess.MongoDb;
// [...]
MongoDbObjectMapper.Instance.RegisterModelExtension<YourCustomClassName>();
This needs to be done only once per application lifetime - for example, in an initialize pipeline processor.
Your own storage
Of course, you don't have to use Sitecore's API to store your custom data. So the alternative would be to manually save data to a custom MongoDB collection or an SQL table. You can then read that data in your aggregation processor, finding it by the ID of currently processed interaction.
The benefit of this approach is that you can decide where and how your data is stored. The downside is extra work of implementing and maintaining this data storage.
TL;DR
What's the best way to handle dependency between types of data that is loaded asynchronously from different backend endpoints?
Problem
My app fetches data from a backend, for each entity I have an endpoint to fetch all instances.
For example api.myserver.com/v1/users for User model and api.myserver.com/v1/things for Thing model.
This data is parsed and placed into data store objects (e.g. UserDataStore and ThingDataStore) that serve these models to the rest of the app.
Question
What should I do if the data that comes from /things depends on data that comes from /users and the fetch operations are async. In my case /things returns the id of a user that created them. This means that if /things returns before /users, then I won't have enough data to create the Thing model.
Options
Have /things return also relevant /users data nested.
This is bad because:
I'll then have multiple model instances User for the same actual user - one that came from /users and one that came nested in /things.
Increases the total payload size transferred.
In a system with some permission policy, data that is returned for /users can be different to /things, and then it'll allow partially populated models to be in the app.
Create an operational dependency between the two data stores, so that ThingsDataStore will have to wait for UserDataStore to be populated before it attempts to load its own data.
This is also bad because:
Design-wise this dependency is not welcome.
Operational-wise, it will very quickly become complicated once you throw in another data stores (e.g. dependency cycles, etc).
What is the best solution for my problem and in general?
This is obviously not platform / language dependent.
I see two possible solutions:
Late initialization of UserDataStore in ThingDataStore. You will have to allow for creation an object that is not fully valid. And you will also need to add method that will give you an information whether UserDataStore is initialized or not. Not perfect, because for some time there will exists an invalid instance.
Create some kind of proxy or maybe a buider object for ThingDataStore that will hold all information about particular thing and will create ThingDataStore object as soon as UserDataStore related with this instance will be received.
Maybe it will help you. Good luck!
I'm making an app that are retrieving messages as PFObjects with Parse, and I retrieve these messages in my viewDidLoad-function. The problem is that this function retrieves the messages every time the page is loaded.
So I thought about making a list in my core data where I save all the id's of my already retrieved objects, and then compare the id of the newest(and possibly already retrieved) object that is being retrieved to the ones in this list.
Because I don't wanna use core data unnecessary, I was just wondering if anyone had a other and more efficient solution to this problem.
Any suggestions would be highly appreciated.
I'd like to store the DocumentSet returned from Model::find() in memcached. However, I get the MongoException below when I try to work with the results after retrieving them from cache. Specifically, when using foreach, the exception is thrown when calling if ($this->_resource->hasNext()) on line 63 of \data\source\mongo_db\Result.php
MongoException
The MongoCursor object has not been correctly initialized by its constructor
I can understand why this would be the case.
My question is, is there anyway to pre-populate a Model::find() or create my own DocumentSet so that I can work with the data? Normally, I'd just convert it to an array and store that in cache. However, I need access to some of the Model methods I've written (ex: Customer::fullName())
Update: I've found a bit of a workound that is ok but not great. I'm saving the Model::find() results as an array in cache $result->to('array'). Then, upon retrieval, I loop through the $results and populate a new array with Model::create($result, array("exists" => true) for each $result;
A DocumentSet returned by Model::find contains a Mongo db cursor. It doesn't load all of the data from the database until the items are iterated. As each item is iterated, a Document is created and is cached in memory into the DocumentSet object. The built-in php function iterator_to_array() can be used to turn the DocumentSet into an array of documents which you could cache.
As you mention in your update, you can also use ->to('array') to prepare for caching and then Model::create() to build it back up. One caveat with that method: when you use ->to('array') it also casts MongoId and MongoDate objects to strings and integers respectively. If you've defined a $_schema for your model and set the 'id' and 'date' types, they will be cast back to the original MongoId and MongoDate objects in the Document returned by Model::create(). If you don't have a schema for all of your fields, it can be a problem. I have a recent pull request that tries to make it possible to do ->to('array') without casting the native mongo objects (also fixes a problem with the mongo objects always being casted when inside arrays of sub-documents).
FWIW, I actually prefer saving just the data in cache because it's less space than serializing a whole php object and avoids potential issues with classes not being defined or other items not initialized when the item is pulled from cache.
I haven't tried this... but I would think you could make a cache strategy class that would take care of this transparently for you. Another example of the great care that went into making Lithium a very flexible and powerful framework. http://li3.me/docs/lithium/storage/cache/strategy
What's the difference between getting an managed object with
- (NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectID
and
- (NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID error:(NSError **)error
What are "registered" objects? What's the difference between "registered" objects and "unregistered" objects?
What are "registered" objects?
Judging from the results I've gotten using these methods, a registered object is one that has been fetched into the MOC. If an object exists in the persistent store but has not been fetched, feeding its objectID to the objectRegisteredForID method will return nil.
How could you even have its objectID if it had not been fetched? Well, I visited this question when implementing a Revert routine. I dumped any unsaved changes by replacing the database with an older copy, cleared the context and then reaccessed it. But I wanted to be able to restore the user's selection of objects to the cache of a table. So, before doing the reversion, I stashed the objectIDs that the user had selected in an array. Then, after the reversion, I rebuilt the table cache using the stashed objectIDs.
When I called objectRegisteredForID using these stashed objectIDs, it always returned nil. (But if I tested this before getting a fresh context, it would return the corresponding object -- which at that point was a fetched, loaded object. Hence my inference as to the meaning of "registered.")
When I called objectWithID using these stashed objectIDs, everything was fine unless the object had been deleted post the last save, in which case it would no longer exist in the database and the invalid but non-nil return would cause exceptions later.
So I used existingObjectWithID:error. If the object still existed, it would be returned. If it no longer existed, the return would be nil and the error's localizedDescription would be "Attempt to access an object not found in store."
Years after the fact:
As Wienke suspects, registered objects are those already in memory for that context. So objectRegisteredForID: will return an object only if somebody else has previously obtained that object.
objectWithID: will return an object if it currently exists in the persistent store.
So the really important distinction is:
objectWithID may go to the persistent store.
Note the corollary: objectWithID may have to perform a fetch. That means locking the store. So:
if the store is already locked by somebody else, objectWithID may block, whereas objectRegisteredForID will never block; and
supposing you had an array of 30 object IDs and you performed objectWithID for each, you'd potentially do 30 separate trips to the store — it'd be much faster to check whether the objects are already registered and then, if any aren't, use an NSFetchRequest to get the rest. Notice that a self in X query can accept an array or set of object IDs to return actual objects even though that wouldn't technically exactly match the normal Objective-C meaning of 'self'.
Falling back on NSFetchRequest is also generally preferable if you have any relationship paths you're going to need prefetched. So there's potentially quite a lot of performance to be gained.
To your first question:
objectRegisteredForID: is the quick & easy way to get the object -- it either returns your object or it returns nil letting you know that it could not. You use this when you either already know why the result might be nil or you don't care.
existingObjectWithID:error: is similar, in that it returns either your object or nil but, in addition, if you pass an error parameter, it will tell you WHY it returned nil. You may want to do this if you plan to do any sort of error reporting (a log message or alert), or error handling (perhaps you plan to take different actions, depending on which kind of error is returned.
EDIT: In addition (per docs), if there is not a managed object with the given ID already registered in the context, the corresponding object is faulted into the context.
I suggest that you break out the "what are registered objects?" portion of your question to a separate question in order to facilitate both getting a better answer (based on the subject line matching the question) and to help future spelunkers who may come looking for an answer.
I was recently confused as to why registeredObject(for objectID: NSManagedObjectID) was returning nil, but there was a simple explanation: the NSManagedObject instances I fetched were not retained: I extracted the information I needed from them and let them be deallocated, which seems to "unregister" them from the managed object context, though they could easily be retrieved using other methods on NSManagedObjectContext. I find the CoreData documentation truly terrible: "registered" is just one of many distinctions that are not clearly explained.