How do I resolve error with insert() with Mongo BasicDBObject - mongodb

Hope this isn't too newBish of a question, but I created a collection of client users (as usersCollection), then I create a user like:
BasicDBObject user = new BasicDBObject("_id", username);
I append a couple more bits to it depending if I have them from the form that the user enters.
But then when I try to insert the user in the usersCollection...
usersCollection.insert(user);
My IDE complains that it cannot resolve method insert(com.mongodb.BasicDBObject)
I don't see the problem... I am using mongodb-driver 3.2.2... if that's even relevant.
Any clue what I doing wrong?

Make sure your usersCollection object class is com.mongodb.DBCollection . From the present information I can only deduce that it's of another type as it does not recognize the insert method.

I changed directions... instead of using a DBObject I instantiated the collection as a document
MongoCollection<Document>
Next I created the user like:
Document user = new Document("_id", username);
(and appended some other bits after that)
Finally, to insert it, simply insertOne()
allUsers.insertOne(user);
Really not sure what I was doing wrong with DBObject but I do think I was making it more complicated than it needed to be. Thanks for the tips though, your questions helped push me to rethink why I was doing it that way to begin with.

Related

Swift Firestore Generate Document ID before creating a document

I am trying to generate a document id to use on two documents in seperate collections.
I am able to achieve this in an Angular PWA, but I'm now working it into an iOS app.
Basically an appointment document is added to a user, then a top level document is created for ease of display and notifications using the same document id
users/uid/appointments/newID
appointments/uid/appointment/newID
All of this takes place in the same ViewController, so in the code I need to generate a temporary document id to use as the id in both collections.
I hope that makes sense....
would let tempId = db.document().documentID do the trick?
I managed to suss it all out.
After creating my collection reference, let's call it myRef, I did the following:
myRef = db.collection("collection_name")
secondRef = db.collection("second_collection")
let tempId = myRef.document().documentid
myRef.document(tempId).setData(myDictionary)
secondRef.document(tempId).setData(otherDictionary)
That helped create the duplicate document id's i needed.
Hope this helps with someone else...
Cheers
Michael

Getting translated records in CommandController

I've searched and debugged the last couple of days how to obtain the
translated version of a DomainModel object in a CommandController in Typo3 v8.7.
In Typo3 4.5/4.7 I've done the following:
- input: DomainModel in default language
- build a query that finds the record with the l10n_parent matching the
given domain model
- obtain a new domain model with the desired sys_language_uid
Unfortunately this does not work in Typo3 v8.7 any more. I always get
the domain model for the default language.
I've traced this down to the method Typo3DbBackend::doLanguageAndWorkspaceOverlay
called via Typo3DbBackend::getObjectDataByQuery
The query returns the correct (translated) row (seen in the debugger and also the mysql query log), but then the variable
$row gets overwritten in doLanguageAndWorkspaceOverlay no matter how I
set the querySettings setLanguageOverlayMode and setLanguageMode.
So what is the correct way to get a translated domain model in a
CommandController?
UPDATE:
I think I'm a step further. If I add ->setQueryLanguage(1) to the query settings, doLanguageAndWorkspaceOverlay() tries to fetch the translated record for language = 1. But in order to succeed I need to trick the FrontendGroupRestriction class by setting $GLOBALS['TSFE']->gr_list = "0,-2";.
The array returned by doLanguageAndWorkspaceOverlay() now contains all translated entries, except the uid, which is still the uid from the record in the main language. The uid of the translated record is stored in _LOCALIZED_UID.
Now my problem now is that I still get the record in the main laguage because DataMapper->mapSingleRow() (called via DataMapper->map()) has some kind of object cache and thus returns the object in the default language (because the uid is still the one of the record in the main language).
All this seems a little hackish. So again my question: what is the correct way to get a translated domain model in a CommandController?
thanks,
mika
p.s.: I've set up the second language in the backend and creating a translated record works just fine. My question is just how to I get an existing translated record in a CommandController.
alternative solution:
based on the solution above, I decided that I can do almost everything
on my own. So what I do now is
i) create an independend querybuilder for the according table:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tableName);`
ii) select the record with the desired l10n_parent and sys_language_uid
$query = $queryBuilder->select('*')
->from($tableName)
->where($queryBuilder->expr()->eq('sys_language_uid', $langId))
->andWhere($queryBuilder->expr()->eq('l10n_parent', $parentUid))
->execute();
iii) fetch all records into an array
$rows = $query->fetchAll();
iv) invoke the DataMapper manually to get the object
$dataMapper = $this->objectManager->get(DataMapper::class);
$translated = $dataMapper->map($className, $rows);
I know it has nothing to do with the ModelRepository any more, but it
works quite fine for now...
that's all folks
My solution to the issue described above:
To avoid invoking the DataMapper as part of the query from
Typo3DbBackend, I used a raw query (argument for ->execute()) and get
back an array, that already went through language overlay etc.
BUT: in
the array the '_LOCALIZED_UID' is still available. So I overwrite the
uid with the value from '_LOCALIZED_UID' and invoke the DataMapper
manually. Quite cumbersome and very hackish to overcome the Typo3
backend shortcomings...

How can I have an association fetch an existing record?

I'd like to write a factory for a blog post, that doesn't create a new user record for every post, but rather pick a random user from those that already exist. How would I do this?
You could randomly order your table, take a record and assign it to your Post. Bear in mind that there is definitely a cleaner way to do this, but here's one that works, obviously assuming your users are already in your test database.
user = User.order("RANDOM()").take #PostgreSQL
user = User.order("RAND()").take #MySQL
post = create(:post, user: user)

Spring Data Couchbase findById always returns null

Am i heading entirely down the wrong road?
Should this work?
I'm trying to build a query that restricts the selection based on a boolean
e.g. findByIdAndFieldIsTrue(id)
This always returns no values. If I narrow this and just do findById(id) i still get no results which seems odd. I have tried a number of permutations of Id & field in the method name but none work.
Entity {
#Id
String id
boolean field
}
interface EntityRepository BaseRepository, Repository {
findByIdAndFieldIsTrue(id)
}
I tried without the BaseRepository thinking maybe the findOne method was interfering but no luck.
Update:
After adding the logger suggested in the answer I can get the query
{"statement":"SELECT META(`mybucket`).id AS _ID, META(`mybucket`).cas AS _CAS, `mybucket`.* FROM `mybucket` WHERE (`id` = \"entity::9627ff50-531d-4191-a9dc-07b48ba77fe9\") AND `_class` = \"com.myrepo.repository.api.Entity\"","scan_consistency":"statement_plus"}
Edit: N1QL forces you to use the USE KEY construct to select by id... That will be much much harder to integrate, looks like the workaround is the easiest path (see below)
I think this is an overlook of query derivation on the #Id field. In Couchbase, that field maps to the document's key and isn't contained in the document's body, so the N1QL query needs to take that into account.
Can you activate logging for the query generation? There's an AbstractN1qlBasedQuery.class logger that will log the generated N1QL in DEBUG mode. It will allow us to see what the query looks like and confirm that a special step must be taken for the #Id field...
I know it wouldn't be as performant if deserialization is complex, but a workaround could be to use findOne and then check the field.
Got this to work with the following:
#Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND META(#{#n1ql.bucket}).id IN $1")
List<Entity> findByIdIn(JsonArray ids);
To get the JsonArray from a list do the following:
import com.couchbase.client.java.document.json.JsonArray;
.
.
.
repository.findByIdIn(JsonArray.from(myList));

How to change live date?

I wonder, How do I change a live data schema with MongoDB ?
For example If I have "Users" collection with the following document:
var user = {
_id:123312,
name:"name",
age:12,
address:{
country:"",
city:"",
location:""
}
};
now, in a new version of my application, if I add a new property to "User" entity, let us say weight, tall or adult ( based on users year ), How to change all the current live data which does not have adult property. I read MapReduce and group aggregation command but, they seem to be comfortable and suitable for analytic operation or other calculations, or I am wrong.
So what is the best way to change your current running data schema in MongoDB ?
It really depends upon your programming language. MongoDB is really good at having a dynamic schema. I think your pattern of thought at the moment is too SQL related whereby you believe that all rows, even if they do not yet have a value, must have the new field.
The reality is quite different. The rows which have nothing meaningful to put into them do not require the field and you can, in your application, just check to see if the returned document has a value, if not then you can assume, as in a fixed SQL schema, that the value is null.
So this is one aspect where MongoDB shines, is the fact that you don't have to apply that new field to the entire schema on demand, instead you can lazy fill it as data is entered by the user.
So just code the field into your application and let the user do the work for you.
The best way to add this field is to write a loop, in maybe the console close or on the primary of your replica (if you have one, otherwise just on the server), like so:
db.users.find().forEach(function(doc){
doc.weight = '44 stone';
db.users.save(doc);
});
That is currently the best way to do something like what your asking.