mongo repository query for array of objects - mongodb

I am using MongoRepository query instead of MongoTemplate for querying list of objects.Below is the sample mongo json values.
{
"host":[
{
"user":"username",
"pass":"password"
},
{
"user":"username1",
"pass":"password"
}
]
}
{
"host":[
{
"user":"username",
"pass":"password123"
},
{
"user":"username123",
"pass":"password"
}
]
}
Need to get list of host Object based on username and password query.
Below is my query
#Query("{'host.user' : { $in : ?0 }, 'host.pass' : { $in : ?1 }}")
public List<Host> getListofHost(String username,String password);
But Actually it is listing all host since username and password is present in list of host,Is there a way to get Actual List of host getListofHost("username","password") and it should return only
"host":[
{
"user":"username",
"pass":"password"
},
{
"user":"username1",
"pass":"password"
}
]
Thanks in Advance

Related

Convert Array to Json in Mongodb Aggregate

I have a Mongo Document in below format:
{
"id":"eafa3720-28e2-11ed-bf07"
"type":"test"
"serviceType_details": [
{
"is_custom_service_type": false,
"bill_amount": 100
}
]
}
"serviceType_details" Key doesn't have any definite schema.
Now I want to export it using MongoDB aggregate to Parquet so that I could use Presto to query it.
My Pipeline Code:
db.test_collection.aggregate([
{
$match: {
"id": "something"
}
},
{
$addFields: {
...
},
}
{
"$out" : {
"format" : {
"name" : "parquet",
"maxFileSize" : "10GB",
"maxRowGroupSize" : "100MB"
}
}
}
])
Now I want to export the value of "serviceType_details" in json string not as array ( when using current code parquet recognises it as an array)
I have tried $convert,$project and it's not working.
Currently the generated Parquet schema looks something like this:
I want the generated Parquet schema for "serviceType_details" to have as string and value should be stringify version of array which is present in mongo document.
Reason for me to have need it as string is because in each document "serviceType_details" details have completely different schema, its very difficult to maintain Athena table on top of it.
You can use the $function operator to define custom functions to implement behaviour not supported by the MongoDB Query Language
It could be done using "$function" like this:
db.test_collection.aggregate([
{
$match: {
"id": "something"
}
},
{
$addFields: {
newFieldName: {
$function: {
body: function(field) {
return (field != undefined && field != null) ? JSON.stringify(field) : "[]"
},
args: ["$field"],
lang: "js"
}
},
},
}
{
"$out" : {
"format" : {
"name" : "parquet",
"maxFileSize" : "10GB",
"maxRowGroupSize" : "100MB"
}
}
}
])
Executing JavaScript inside an aggregation expression may decrease performance. Only use the $function operator if the provided pipeline operators cannot fulfill your application's needs.

Query Mongo Collection of nested document of same type

I have a not so unique requirement but i am just finding the right terminology to search, since i only keep getting results on how to query list/ array fields or nested elements.
Here is my class (document type)...
public class Item {
private String identity = null;
private String name = null;
private String type = null;
private List<Item> grouping = null;
}
Thus, some entity instances of this type could get complex as shown below...
{
"identity":"ITEM-1",
"name":"Pack-1",
"type":"Bundle",
"grouping":[
{
"identity":"ITEM-2",
"name":"Book",
"type":"Atomic Unit"
},
{
"identity":"ITEM-3",
"name":"Stationary",
"type":"Bundle",
"grouping":[
{
"identity":"ITEM-4",
"name":"Pen",
"type":"Atomic Unit"
},
{
"identity":"ITEM-5",
"name":"Paper",
"type":"Atomic Unit"
},
{
"identity":"ITEM-6",
"name":"Paraphernalia",
"type":"Bundle",
"grouping":[
{
"identity":"ITEM-7",
"name":"Eraser",
"type":"Atomic Unit"
},
{
"identity":"ITEM-8",
"name":"Ruler",
"type":"Atomic Unit"
},
{
"identity":"ITEM-9",
"name":"Compass",
"type":"Atomic Unit"
}
]
}
]
}
]
}
Now my requirement is to be able to search for Book or Pen or Compass and must be able to fetch the record ITEM-1. How do I achieve this in Mongo Query. I am using Spring Data Mongo Repository approach on my data abstraction service layer.
Thanks in advance for all the help.
my requirement is to be able to search for Book or Pen or Compass and
must be able to fetch the record ITEM-1.
You can try this query from mongo shell, and it fetches the document:
var SEARCH_ITEMS = [ "Book", "Pen", "Compass" ]
var ATOMIC = "Atomic Unit"
db.collection.find( {
$or: [
{ "type": ATOMIC, name: { $in: SEARCH_ITEMS } },
{ "grouping.type": ATOMIC, "grouping.name": { $in: SEARCH_ITEMS } },
{ "grouping.grouping.type": ATOMIC, "grouping.grouping.name": { $in: SEARCH_ITEMS } },
{ "grouping.grouping.grouping.type": ATOMIC, "grouping.grouping.grouping.name": { $in: SEARCH_ITEMS } }
]
} )

GraphQL query on Embedded/Nested Field in MongoDB

How to specify a query condition on fields in an embedded/nested document in MongoDB using GraphQL ?
In mongo shell I can easily get the document by
db.users.find({ 'contacts.phone': '8148*****' } ).pretty();
Which will fetch me the record
{
"_id" : ObjectId("5c93c0601a29f5183929c02c"),
"name" : "Athul",
"contacts" : {
"address" : "Some address",
"phone" : "8148*****",
"email" : "***#live.com"
},
"__v" : 0
}
On my GraphQL Schema I have defined the query as mentioned below
...
input ContactsInput {
address: String
phone: String
email: String
}
input userInput {
name: String
contacts: ContactsInput
}
type RootQuery {
users(user: userInput): [User!]!
}
....
The Resolver for users is
...
const User = require('../../models/user');
...
users: async args => {
try{
const query = JSON.parse(JSON.stringify(args.user));
const userList = await User.find(query);
if(!userList) {
throw new Error("No user found");
}
return userList;
} catch(err){
throw err;
}
}
...
(It works fine if I search with the name)
And in GraphiQL I'm trying to get the same record by the below query
query{
users(user: {contacts: {
phone: "8148*****"
}}){
name
contacts{
email
phone
}
}
}
with which I'm not able to get the same record.
Because at the back end its executing
db.users.find({ contacts: { phone: '8148405590' } });
which is not equivalent to
db.users.find({ 'contacts.phone': '8148*****' } );
Can you please help me resolve this issue ?
It looks like you have to build the query object before sending it to mongodb.
You can try something like:
const tempQuery = {'contacts.phone': args.user.contacts.phone}
const query = JSON.parse(JSON.stringify(tempQuery));
You just have to make sure that all the values(user.contacts.phone) exist in the input, and if you want to have other queries you have to write all different combinations (ex: contacts.email).
Otherwise you could have a look into this blog post about GraphQL to MongoDB and the library graphql-to-mongodb, but to implement it you might have to refactor a bit of your code.

MongoDB - How to find() a field in a collection that has a reference to another collection?

So I have this field contacts.envCon.name which is inside the Projects collection but when I see them in mongo they are like this:
"envCon" : {
"$ref" : "contacts",
"$id" : ObjectId("5807966090c01f4174cb1714")
}
After doing a simple find based on past ObjectId:
db.getCollection('contacts').find({_id:ObjectId("5807966090c01f4174cb1714")})
I get the following result:
{
"_id" : ObjectId("5807966090c01f4174cb1714"),
"name" : "Terracon"
}
By the way: I'm using Meteor if there is anyway to do this directly with publish/suscribe methods.
Yes, you can do this join inside a publication using the very popular reywood:publish-composite package.
With your model:
Meteor.publishComposite('projectsWithContacts', {
find: function() {
return Projects.find(); // all projects
},
children: [
{
find: function(p) { // p is one project document
return Contacts.find(
{ _id: p.envCon.$id }, // this is the relationship
{ fields: { name: 1 } }); // only return the name (_id is automatic)
}
},
]
});

mongodb update push sub-subdocument

The question is quite easy. I have the following document in mongoDb:
_id : ObjectId("519e3c14ade67153e9a003a0")
status:1,
name:"name",
details:
{
crm:115,
webs:
[
{ tag:"blog" , url:"http://..."}
],
contacts:
[
{
_id:ObjectId("009e37e1ade67153e9a0039e"),
name:"me",
phones:
[
{ tag:"home", number:"123..." },
{tag:"mobile", number:"123456789"}
]
}
]
}
I am trying to update one fo the phones in the subdocument details.contacts doing this:
db.new.update(
{
_id : ObjectId("519e3c14ade67153e9a003a0"),
"details.contacts._id": ObjectId("009e37e1ade67153e9a0039e"),
"details.contacts.phones.tag":"home"
},
{
$set:
{
"details.contacts.$.phones.$":
{
tag:"home",
number:"965923777"
}
}
})
and finally I get the following error: Cannot apply the positional operator without a corresponding query field containing an array.
There is anyway to update the document in this way or i should send all the phones to update this field?