I search through the half of the Internet but found either nothing or outdated solutions with db.eval(). Hence my question.
I have some code using mongo driver 3.5.0:
MongoDatabase db = mongoClient.getDatabase 'mydb'
println db.runCommand( new BasicDBObject( eval:'db.version()' ) )
Exception in thread "main" com.mongodb.MongoCommandException: Command failed with error 13: 'not authorized on mydb to execute command { eval: "db.version()", $readPreference: { mode: "secondaryPreferred" }, $db: "mydb" }' on server localhost:27017. The full response is { "ok" : 0.0, "errmsg" : "not authorized on mydb to execute command { eval: \"db.version()\", $readPreference: { mode: \"secondaryPreferred\" }, $db: \"mydb\" }", "code" : 13, "codeName" : "Unauthorized" }
at com.mongodb.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:115)
at com.mongodb.connection.CommandProtocol.execute(CommandProtocol.java:107)
I can run this command in the shell:
mongo "mongodb://admin:admin#somehost:27003/mydb?replicaSet=myset" -eval 'db.version()'
outputs
3.6.6
If I run the command from inside the shell:
db.runCommand( { 'eval':'db.version()' } )
I'm also getting
{
"operationTime" : Timestamp(1536931496, 11),
"ok" : 0,
"errmsg" : "not authorized on mydb to execute command { eval: \"db.version()\", $db: \"mydb\" }",
"code" : 13,
"codeName" : "Unauthorized"
}
The user I'm connecting with looks like:
{
"_id" : "mydb.admin",
"user" : "admin",
"db" : "mydb",
"roles" : [
{
"role" : "readWrite",
"db" : "mydb"
},
{
"role" : "dbAdmin",
"db" : "mydb"
},
{
"role" : "userAdmin",
"db" : "mydb"
},
{
"role" : "dbOwner",
"db" : "mydb"
}
]
}
What am I missing?
Do I need special privileges for eval?
As per mongodb documentation, you need a role that grants anyAction on AnyResource.
Related
My Document Looks like below .I need to get the value of Email Systems.Bob and Email Systems.System = Bob .I have tried with the below MongodbQuery but not getting proper results .Any one can suggest how to get the desired results with Mongodb Java driver.
Query:
db.users.find(
{ "Email Systems": { $elemMatch: {$eq: "Atlas"} } } );
{
"_id" : ObjectId("5f0890e870e631865877e"),
"user" : "testuser",
"Email" : "testuser#sample.com",
"Batch Systems" : [
"STAR",
"STORY",
"ITEMS",
],
"Email Systems" : [
{
"Bob" : {
"System" : "Bob",
**"result"** : true
}
},
{
"Wild" : {
"System" : "Wild",
"result" : true
}
},
{
"CRaft" : {
"System" : "Craft",
"result" : false
}
}
]
}
To fetch Email Systems.Bob you can use this query:
db.users.find({ "Email Systems.Bob": { $exists: true} })
To fetch Email Systems[].{dynamic-key}.System == 'Bob'.
I don't think it will be possible to pass some kind of regex for dynamic key in the query, AFAIK.
Here you might fetch all documents with field Email Systems and filter it in your java code. (not efficient though)
db.users.find({ "Email Systems": { $exists: true} })
I have got a below document in Mongodb collection , need to get the value of result of false with Java syntax .Any help can be appreciated .
{
"_id" : ObjectId("5f0890e870e631865877e"),
"user" : "testuser",
"Email" : "testuser#sample.com",
"Batch Systems" : [
"STAR",
"STORY",
"ITEMS",
],
"Email Systems" : [
{
"Bob" : {
"System" : "Bob",
**"result"** : true
}
},
{
"Wild" : {
"System" : "Wild",
"result" : true
}
}
{
"CRaft" : {
"System" : "Craft",
"result" : false
}
}
],
I can't go like Email Systems.Bob.result ,Email Systems.Wild.result,Email Systems.Craft.result .Can anyone suggest how to get the result value from all systems with Java synatax.
I want to make partial updates by adding an element in my users list:
"users" : [
{
"password" : "pwd",
"level" : "admin",
"user_name" : "XX",
"last_name" : "YY",
"first_name" : "ZZ"
}
]
using Kibana I've tried this request:
POST my_index/user/1/_update
{
"script" : {
"source": "ctx._source.users.add(params.user)",
"lang": "painless",
"params" : {
"user": {
"user_name" : "user",
"first_name" : "XX",
"last_name" : "XX",
"level" : "simple",
"password" : "pwd!#"
}
}
}
}
it works fine:
"users" : [
{
"password" : "pwd",
"level" : "admin",
"user_name" : "XX",
"last_name" : "YY",
"first_name" : "ZZ"
},
{
"password" : "pwd!#",
"level" : "simple",
"user_name" : "user",
"last_name" : "XX",
"first_name" : "XX"
}
]
I want to do it using java client, I've tried this code:
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("user_name", user.getUserName());
builder.field("first_name", user.getFirstName());
builder.field("last_name", user.getLastName());
builder.field("level", user.getLevel());
builder.field("password", user.getPassword());
}
builder.endObject();
params.put("user", Strings.toString(builder));
UpdateByQueryRequest setScript = request.setScript(
new Script(
ScriptType.INLINE, "painless",
"ctx._source.users.add(params)",
params));
request.setScroll(TimeValue.timeValueMinutes(10));
BulkByScrollResponse bulkResponse = restHighLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
as result, I had:
"users" : [
{
"password" : "pwd",
"level" : "admin",
"user_name" : "XX",
"last_name" : "YY",
"first_name" : "ZZ"
},
{
"user" : """{"user_name":"XX","first_name":"XX","last_name":"XX","level":"XX","password":"XX"}""",
"ctx" : {
"_routing" : null,
"_parent" : null,
"_index" : "administration",
"_type" : "environnement",
"_id" : "1",
"_version" : 24
}
}
]
so it's not correct, I want to have only user information added to users and I want to do not index ctx informations.
Thanks !
A bit late but ... there's a typo in your script, you add params instead of params.user.
UpdateByQueryRequest setScript = request.setScript(
new Script(
ScriptType.INLINE, "painless",
"ctx._source.users.add(params.user)", <-- here
params));
request.setScroll(TimeValue.timeValueMinutes(10));
Anyway, this may not fix it, I've encountered similar problems and found that the easiest solution was to pass each value as a param and create the object once in the script, which would give :
parameters.put("user_name", user.getUserName());
parameters.put("first_name", user.getFirstName());
parameters.put("last_name", user.getLastName());
parameters.put("level", user.getLevel());
parameters.put("password", user.getPassword());
request.setScript(new Script(
ScriptType.INLINE,
"painless",
"ctx._source.users.add(params)",
parameters));
request.setScroll(TimeValue.timeValueMinutes(10));
BulkByScrollResponse bulkResponse = restHighLevelClient.updateByQuery(request,RequestOptions.DEFAULT);
Stack trace
Exception in thread "main" com.mongodb.MongoCommandException: Command
failed with error 13: 'not authorized on mongo_chatbot to execute
command { insert: "test", ordered: true, documents: [ { _id:
ObjectId('5b2c9ee1a1b5e20ed53b7237'), name: "pavan", regd: 103, cgpa:
"122" } ] }' on server dev-ng-mongo1.phenompeople.com:27017. The full
response is { "ok" : 0.0, "errmsg" : "not authorized on mongo_chatbot
to execute command { insert: \"test\", ordered: true, documents: [ {
_id: ObjectId('5b2c9ee1a1b5e20ed53b7237'), name: \"pavan\", regd: 103, cgpa: \"122\" } ] }", "code" : 13 }
I am trying to map a successful MongoDB Aggregation to morphia but I am not able to get a satisfying result. I fails everytime but I cannot figure out why. Maybe someone of you could help me to state the aggregation correctly in morphia. My MongoDB Query looks like the following:
db.user.aggregate([{$match: { roles: "MEMBER" }}, {$group:{_id: "$roles", sum:{$sum: "$payments.2039.amount"}}}])
Roles is an array and the aggregation works fine and outputs:
{ "_id" : [ "MEMBER" ], "sum" : 100 }
I tried to do this in morphia with this java code:
final Query<User> query = datastore.createQuery(User.class).field("roles").in(Lists.newArrayList(Role.MEMBER));
final Iterator<AggregatePayments> aggregatePayments = datastore
.createAggregation(User.class)
.match(query)
.group("$roles", grouping("sum", sum("payments." + currentSeason + ".amount")))
.out(AggregatePayments.class);
But, unfortunately, this fails with the following exception:
com.mongodb.MongoCommandException: Command failed with error 17276 (Location17276): 'Use of undefined variable: roles' on server localhost:27017. The full response is { "ok" : 0.0, "errmsg" : "Use of undefined variable: roles", "code" : 17276, "codeName" : "Location17276" }
My problem is now finding out why this works in MongoDB but not in morphia. When I try to leave out the "$" at roles variable for _id in morphia I get the following exception:
com.mongodb.MongoCommandException: Command failed with error 16996 (Location16996): 'insert for $out failed: { connectionId: 1419, err: "can't use an array for _id", code: 2, codeName: "BadValue", n: 0, ok: 1.0 }' on server localhost:27017. The full response is { "ok" : 0.0, "errmsg" : "insert for $out failed: { connectionId: 1419, err: \"can't use an array for _id\", code: 2, codeName: \"BadValue\", n: 0, ok: 1.0 }", "code" : 16996, "codeName" : "Location16996" }
Any help appreciated! Thank you very much!
Using MongoDB version 3.6 and current morphia build 1.4-SNAPSHOT.
EDIT:
What seems really strange to me is that above Query in MongoDB works but the query generated by morphia not. But the manually edited Query in MongoDB and the generated one by morphia seem to correspond closely to another. Does anyone see any mistakes? Generated query is as follows:
11040 [qtp104739310-39] DEBUG org.mongodb.driver.protocol.command - Sending command '{ "aggregate" : "user", "pipeline" : [{ "$match" : { "roles" : { "$in" : ["MEMBER"] } } }, { "$group" : { "_id" : "$roles", "sum" : { "$sum" : "$payments.2039.amount" } } }, { "$out" : "AggregatePayments" }], "cursor" : { }, "$db" : "sua", "$readPreference" : { "mode" : "primaryPreferred" } }' with request id 19 to database sua on connection [connectionId{localValue:2, serverValue:1419}] to server localhost:27017
and produces the exception:
com.mongodb.MongoCommandException: Command failed with error 16996 (Location16996): 'insert for $out failed: { connectionId: 1419, err: "can't use an array for _id", code: 2, codeName: "BadValue", n: 0, ok: 1.0 }' on server localhost:27017. The full response is { "ok" : 0.0, "errmsg" : "insert for $out failed: { connectionId: 1419, err: \"can't use an array for _id\", code: 2, codeName: \"BadValue\", n: 0, ok: 1.0 }", "code" : 16996, "codeName" : "Location16996" }
When manually editing the query in MongoDB I can also use $group:{_id: "$roles".... Seems quite strange to me...
I didn't recognize the difference between morphia's "out()" and "aggregate()" method. "out()" changes the collection in the MongoDB store which was not intended. Using "aggregate()" now solved all problems:
final Query<User> query = datastore.createQuery(User.class).field("roles").in(Lists.newArrayList(Role.MEMBER));
final Iterator<AggregatePayments> aggregatePayments = datastore
.createAggregation(User.class)
.match(query)
.group("roles", grouping("sum", sum("payments." + currentSeason + ".amount")))
.aggregate(AggregatePayments.class);
Works now as expected with morphia 1.4.0-SNAPSHOT (most recent build from git master) and MongoDB 3.6.