Spring data and MongoDB - bidirectional connection of documents - mongodb

I have two Documents in my Spring data - MongoDB application:
The first one is Contact and looks like this:
public class Contact {
...
private List<Account> accounts;
and the second one is Account and looks like this:
public class Account {
...
private Contact contact;
My question now is, whether there is a better way of:
1. create contact object
2. save contact object into database
3. create account object
4. set contact object into account object
5. save account object into database
6. set created account object into contact object
7. update contact object
These are many steps and I will avoid to do such a long list to get Contact and Account connected bidirectional.

Try this approach
MongoDB is a NOSQL DB and hence there is no need of an order to be preserved, such as create and store contact object and then do so more in a sequential way.
Maintain a sequence for Contact and Account object. Before storing these two records get the next number in the sequence and insert the Contact and Account documents.
References for autoincrement sequence
https://docs.mongodb.com/v3.0/tutorial/create-an-auto-incrementing-field/
https://www.tutorialspoint.com/mongodb/mongodb_autoincrement_sequence.htm
Pseudo Code:
Get the next Sequence of Contact and Account Id
Add the id's to respective documents
Insert the Documents in Mongodb
While retrieving the records you can use $lookup which is a left outer join.
Please note that chance of loss of integrity in data can happen if one insert is happened successfully and other insert did not happen for some reason.
We dont have transaction support in Mongodb across collections, more info.

Related

How to find a random user with relations in laravel eloquent

I have the following query where I am generating a random user.
User::inRandomOrder()
->where('role', 'lender')
->whereNotIn('id', $this->lender_ids)
->where('verified', 'verified')
->first();
Now, I want to add another where condition to check if the user has at least one transaction. The problem here is that transactions are in another table and I do have a one-to-many relation with users and transactions where each user can have multiple transactions but a transaction can belong to only one user.
Now, I want to add a where condition to ensure that this random user must have at least one transaction. So how do I do that?
I think has will solve your problem, it checks the existence of relationship, try this:
User::inRandomOrder()
->where('role', 'lender')
->whereNotIn('id', $this->lender_ids)
->where('verified', 'verified')
->has('transactions')
->first();
Source: https://laravel.com/docs/8.x/eloquent-relationships#querying-relationship-existence

CloudKit predicate: Search multiple reference fields with predicate of CKQuery

Using Apple CloudKit, I have a record user and a join table record to connect users and to save the state of the relationship. This means that users can request to be friends and the other party has to accept first.
Now I want to query for those relationship records the user was a part of. This means in the CKReference field Sender and the createdBy field (also CKReference).
How do I build a valid predicate for CKQuery to find records where either the sender or the createdBy is equal to the current user?
Apparently CKQuery doesn't support OR and CONTAINS works only on Strings...
As #Thunk pointed out. Not possible as of today

How to create records concurrently in Postgres with ActiveRecord and Sidekiq

I have a Sidekiq worker, which makes an API call, parses the returned json and creates ActiveRecord objects (products). Since the products belong to a brand and the product json also contains the data for the brand, the worker does the following before actually saving the product to the database:
check if the brand exists in the database by checking its unique api_id (the id, with which the brand comes from the api, in the db, there is a unique index on this column);
if it does - fetch its primary id;
if is doesn't - create it and get its primary id
I have implemented this like so:
def brand_id(brand_json)
Brand.where(api_id: brand_json[:api_id]).pluck(:id).first.presence ||
Brand.create!(name: brand_json[:name], api_id: brand_json[:api_id]).id
end
After that the worker creates the product with the brand_id set to the fetched id.
Now I am thinking of the following scenario:
two workers simultaneously fetch data for two products that belong to the same brand that doesn't yes exist in the database;
worker 1 one checks for the brand and doesn't find it;
shortly after that worker 2 checks for the brand and doesn't find it;
worker 1 creates the brand;
Now what happens with worker 2? My assumption - it tries to create the brand, but an error at the database level occurs, as there is already a record with the same api_id? (probably ActiveRecord::RecordNotUnique error is raised?)
Also, how do I handle this case and this type of errors in the context of Sidekiq and ActiveRecord? Should I somehow implement a table-wide lock on the brands table to prevent such things? If yes - than I will not be able to concurrently create products, as at any given time only one worker will have access to the brands table, which is required for creating a product.
Or maybe I should wrap my brand_id(brand_json) method in transaction like so:
def brand_id(brand_json)
ActiveRecord::Base.transaction do
Brand.where(api_id: brand_json[:api_id]).pluck(:id).first.presence ||
Brand.create!(name: brand_json[:name], api_id: brand_json[:api_id]).id
end
end
Please, advise.
Put the unique index constraints (possibly in the form of a multi column index) in the DB.
Just try to create the object. The database will prevent you from making more than one.
Only the thread that succeeded in creating the initial object (no exception occurred) is allowed to proceed with extra processing.

Set a lookup field value in dynamics crm for multiple records imported by ssis script

i am pushing data from SQL server using ssis into my custom entity Transaction
this transaction has a lookup filed Contact and some other simple field like email amount
i can successfully import data into the crm only when i push email id and amount ,
whenever i try to set lookup field value it require entity reference id , this is where i am stuck in our database there is no entity reference id we only have name
how can i set look up filed value if i don't have entity reference id , since it is a SQL data it has thousand of records
can i set my contact lookup filed value in crm itself based on email id like lets say i imported the data and once the data is imported into crm lookup filed value will set to that particular contact who has the email id which we imported into crm
i hope i am making myself clear please help me out
thanks
Inside your script component (I believe you use this approach) you will have to write code that will fetch required data from CRM using RetreiveMultiple queries.

Mongodb Schema considering sub-document to avoid multiple reads

I am trying to come up with a MongoDB document model and would like others opinions. I want to have a Document that represents an Employee. This table will contain all attributes of an employee (I.e. firstName, LastName). Now where I am stuck coming from the relational realm, is the need to store a list of employees an employee can access. In other words lets say Employee A is a Manager. I need to store the direct reports that he manages, in order to use this in various applications. In relational I would have a mapping table that tied an employee to many employees. In mongo not being able join documents, do you think I should utilize an embeded (sub-document) to store the list of accessible employees as part of the Employee document? Any other ideas ?
Unless your using employee groups (Accounting, HR, etc) You'll probably be fine adding the employee name, mongo Object ID, and any other information unique to that manager / employee relationship as a sub document to the managers document.
With that in place you could probably do your reporting on these relationships through a simple aggregation.
This is all IMHO, and begs the question; Is simple aggregation another oxymoron like military intelligence?