How to query date from mongodb using graphql? - mongodb

I am trying to find documents by DateTime.
I have the following sample of mongo document:
{
"_id" : ObjectId("5df8ea55ac02282c15917e46"),
"title" : "Bán gấp căn 01 DT 62m2 căn góc, giá 1,05 tỷ. LH C Nga 0979441985",
"address" : "La Khê - Hà Đông",
"avatar" : "https://file4.batdongsan.com.vn/crop/200x200/2019/12/07/20191207173723-31f3_wm.jpg",
"price" : "1.05 Tỷ",
"lat" : 20.9719924926758,
"lon" : 105.756340026855,
"id" : 15504225,
"area" : "62 m²",
"cat" : "Bán căn hộ chung cư",
"date" : "17/12/2019",
"room" : 2,
"DateTime" : ISODate("2019-12-17T22:00:36.136+08:00")
}
I have defined a schema:
const sellType = new GraphQLObjectType({
name:'Sell',
fields: () => ({
_id:{type:GraphQLString},
id:{type:GraphQLString},
title:{type:GraphQLString},
address:{type:GraphQLString},
avatar:{type:GraphQLString},
price:{type:GraphQLString},
DateTime:{type:GraphQLDateTime}
})
})
I have also defined the root query:
const RootQuery = new GraphQLObjectType({
name:'RootQueryType',
fields: {
property_for_sell_by_datetime:{
type: sellType,
args:{DateTime:{type:GraphQLDateTime}},
resolve(parent, args){
return sell.find({DateTime:new Date(args.DateTime)})
}
}
}
})
But I don't know why I cannot find any document using:
{
property_for_sell_by_datetime(DateTime:"2019-12-17T14:00:36.136Z"){
_id
DateTime
}
}
Edit:
I tired to use findOne. It works. But find is not working
Edit2:
I need to define type as GraphQLList

to use find instead of findOne, I need to define the type as GraphQLList

Related

Need to get the result of query combining the databases and its collections

I am new to Mongodb and need some help ( as below )
Database: Test1
Collection Name : info_123
{"_id" : ObjectId("5e975401c0178289eb6ac88a"),
"name" : "hello_123",
"model" : "omni",
"status:true"
}
Collection Name : info_abc
{"_id" : ObjectId("5e975401c0178289eb6ac08a"),
"name" : "beta_a",
"model" : "aqua",
"status" :"true"
}
Database:Test2
collection name : info_A
{"_id" : ObjectId("5e975401ce178289eb6ac88a"),
"name" : "hello_123",
"model" : "aqua",
"status" :"false"
}
Collection Name : info_B
{"_id" : ObjectId("5e975401c0178289ebsac08a"),
"name" : "alpha_123",
"model" : "aqua",
"status" :"false"
}
Collection Name : Beta_B
{"_id" : ObjectId("5e975401c0178289ebsac08a"),
"name" : "alpha_123",
"model" : "aqua",
"status" :"false"
}
Problem : Need the query across all the databases(test1,test2 etc) where collection name is like "info_" and "name" field in that collection should not contain "hello" and then group by "model" field and status is "True".
db = db.getSiblingDB("admin");
dbs = db.runCommand({ "listDatabases": 1 }).databases;
// Iterate through each database and get its collections.
dbs.forEach(function(database) {
db = db.getSiblingDB(database.name);
cols = db.getCollectionNames().filter(?);
// Iterate through each collection.
cols.forEach(function(col) {
// Do something with each collection.
print(col);
});
sudo
});
You can get the name of the databases like this:
const infoReg = /^info_/;
db.getMongo().getDBNames().forEach(dbName => {
const siblingDb = db.getSiblingDB(dbName);
const collectionList = siblingDb.getCollectionNames().filter(collectionName => {
if (collectionName.match(infoReg)) {
return true;
}
});
// db.getCollection(collectionList[0]).find({});
print(collectionList);
});
By Regex you can find the collection that has your criteria.

how to update one table with the _id from another table in Mongodb

I exported data from a MySQL database into JSON and imported it into MongoDB. The problem:
When I imported clients, MongoDB created its own _id field (I know this is built in functionality, but MySQL used a clientID, autoincrementing integer).
SO, when I imported my appointments collection, the clientID was renamed oldClientID. I'd like the clientID field to be the ObjectID of the corresponding client.
My schemas:
const apptSchema = new mongoose.Schema({
ID: Number,
clientID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Client'
},
oldClientID: Number,
...other field data
});
const clientSchema = new mongoose.Schema({
ID: Number,
familyID: Number,
first: String,
last: String,
});
Sample Patient Data:
{
"_id" : ObjectId("5d82240f7c8ddd03b62aee6a"),
"ID" : 18,
"familyID" : 6,
"first" : "Jane",
"last" : "Doe"
}
Sample Appointment Data
{
"_id" : ObjectId("5d82c8b95627367d122087f9"),
"ID" : 1885,
"oldPatientID" : 18,
"scheduled" : ISODate("2015-08-05T11:20:00Z"),
"note" : ""
},
{
"_id" : ObjectId("5d82c8b95627367d122088a8"),
"ID" : 2066,
"oldPatientID" : 18,
"scheduled" : ISODate("2015-09-17T16:00:00Z"),
"note" : ""
}
What appointments should look like:
{
"_id" : ObjectId("5d82c8b95627367d122087f9"),
"ID" : 1885,
"clientID": ObjectId("5d82240f7c8ddd03b62aee6a"),
"oldPatientID" : 18,
"scheduled" : ISODate("2015-08-05T11:20:00Z"),
"note" : ""
},
{
"_id" : ObjectId("5d82c8b95627367d122088a8"),
"ID" : 2066,
"clientID" : ObjectId("5d82240f7c8ddd03b62aee6a"),
"oldPatientID" : 18,
"scheduled" : ISODate("2015-09-17T16:00:00Z"),
"note" : ""
}
I am open to learning how to achieve this in the mongo shell or using mongoose in express (or if there is another cool way, like in Robo3T).
MongoDB will always use _id as the primary key, this behavior cannot be overwritten, though you can use the _id with values from your custom id. Though this might be confusing, it is better to use indexing on your custom id, and you don't need to use ObjectId for the custom index field, but can use your own custom id schema, like UUID or an incrementing integer value etc. though it has to be generated/incremented by you or some framework, like JPA
Check Indexes
For Mongoose, you can do;
new mongoose.Schema({
customId: { type: Number, index: true }
...other field data
});
with index: true
Ok, this worked out for me, although I'm sure there has to be an easier way:
db.getCollection("appts").aggregate(
[
{
"$lookup" : {
"from" : "clients",
"localField" : "clientID",
"foreignField" : "ID",
"as" : "CLIENT"
}
},
{
"$lookup" : {
"from" : "appttypes",
"localField" : "type",
"foreignField" : "ID",
"as" : "TYPE"
}
},
{
"$lookup" : {
"from" : "apptstatuses",
"localField" : "status",
"foreignField" : "ID",
"as" : "STATUS"
}
},
{
"$project" : {
"_id" : "$_id",
"clientID" : "$CLIENT._id",
"scheduled" : "$scheduled",
"note" : "$note",
}
},
{
"$out" : "apptslinked"
}
]
);
Then I exported that as JSON, dropped the appts table, and did a mongoimport using that file.

meteor client find is not working due to $eq

I subscribed to my servers's publication as follows:
Template.observedQuestions.onCreated(function(){
var self = this;
self.autorun(function(){
self.subscribe('observedQuestionsFeed');
});
});
Now I need to fetch my data using helper function:
Template.observedQuestions.helpers({
observedQuestionsList : function(){
questions = Questions.find({
observedByUsers : {$exists: true,$elemMatch:{$eq:Meteor.userId()}}});
return questions;
}
});
but it does not work due to $eq being not recognised in minimongo.
How to solve it?
doc sample:
{
"_id" : "rP4JP8jkprwwi3ZCp",
"qUserId" : "NLLW3RBXqnbSGuZ3n",
"type" : "question",
"date" : ISODate("2016-02-13T11:23:10.845Z"),
"subject" : "test",
"question" : "test",
"replies" : [
{
"rID" : "LphcqKnkTHf25SCwq",
"rUserID" : "NLLW3RBXqnbSGuZ3n",
"date" : ISODate("2016-02-13T11:23:10.847Z"),
"answer" : "reply1."
},
{
"rID" : "HxaohnEgxwNJLtf2z",
"rUserID" : "NLLW3RBXqnbSGuZ22",
"date" : ISODate("2016-02-13T11:23:10.848Z"),
"answer" : "reply2"
}
],
"observedByUsers" : [ "Bi24LGozvtihxFrNe" ]
}
Judging from your sample Questions document, the field observedByUsers is a simple array which contains user IDs.
As a result, you could simply use the following query:
Questions.find({observedByUsers: Meteor.userId()});

how to validate date range and insert new data in a single command

Let's say i have a collection named "rooms" that contain 20 documents, each document has a "start_date" and "end_date" in "room_record" field, now i wanted to insert a new record in the room_record field but i wish to check the new record start and end date isn't in between the existed record start_date and end_date if it is overlap then the query have to fail or not insert the new record else insert the new record. i have found a similar question in here
Query and Insert with a single command however i can't solve my problem by trying their approach.
this is what i have so far
room collections document
{
"_id" : "0JikW3",
"room_capacity" : "2",
"room_description" : "bla bla bla",
"room_image" : [
"http://i.imgur.com/n99LkGg.jpg",
"http://i.imgur.com/zLPNy83.jpg"
],
"room_price" : "250",
"room_record" : {
"end_date" : "2014-08-18T13:54:52.891Z",
"start_date" : "2014-08-16T13:54:52.891Z"
},
"room_status" : "0",
"room_type" : "A"
}
this is my approach
//build a record with new start and end date
var room_record = {
"booking_id":bookingID,
"start_date":data.startDate,
"end_date":endDate
}
rooms.update(
{"room_record":{"$elemMatch":{"room_record.start_date":{"$lt":data.startDate},"room_record.end_date":{"$gt":endDate}},"room_type":data.roomType}},
{ $setOnInsert:{"room_record":room_record}},
{upsert:1},
function(err,result){
if (err) return callback(err, null);
callback(err, result);
console.log(result)
})
after perform my approach this is what i get in my room collection, instead of insert into the existing document it created a new document.
{
"_id" : ObjectId("53ef765974574412ef7d0a49"),
"room_record" : {
"end_date" : ISODate("2014-08-21T13:54:52.891Z"),
"start_date" : "2014-08-19T13:54:52.891Z"
}
}
this is the result i expected
{
"_id" : "0JikW3",
"room_capacity" : "2",
"room_description" : "bla bla bla",
"room_image" : [
"http://i.imgur.com/n99LkGg.jpg",
"http://i.imgur.com/zLPNy83.jpg"
],
"room_price" : "250",
"room_record" : [{
"end_date" : "2014-08-18T13:54:52.891Z",
"start_date" : "2014-08-16T13:54:52.891Z"
},{
"end_date" : ISODate("2014-08-21T13:54:52.891Z"),
"start_date" : "2014-08-19T13:54:52.891Z"
}],
"room_status" : "0",
"room_type" : "A"
}
your help is appreciated, thank you !
$elemMatch only works for array field.
Your update fails to find any matched document because your room_record is a sub-document, not array. Then upsert affects to insert a new document.
According to the output you expect, I assume that you want to push a new record into the array whose document maybe exist, so you can not adopt $setOnInsert as another question did.
Following code for your information, running in mongo shell.
var startDate = ISODate("2014-08-17T13:54:52.891Z");
var endDate = ISODate("2014-08-18T17:54:52.891Z");
var roomType = "A";
var room_record = {
"start_date" : startDate,
"end_date" : endDate
};
// check if any document overlapped by the time interval
db.rooms.find({
"room_record" : {
"$elemMatch" : {
"start_date" : {
"$lte" : startDate
},
"end_date" : {
"$gte" : endDate
}
}
},
"room_type" : roomType
}).forEach(printjson);
// Push new record into array field "room_record" if the record has not been overlapped by any element in the array.
// Please note that update will fail and produce an error if query succeeds and "room_record" exists but is not an array field.
// New document will be inserted into collection if no document matched.
db.rooms.update({
"room_record" : {
$not : {
"$elemMatch" : {
"start_date" : {
"$lte" : startDate
},
"end_date" : {
"$gte" : endDate
}
}
}
},
"room_type" : roomType
}, {
$push : {
"room_record" : room_record
}
}, {
upsert : true
});

Geo spatial queries with Doctrine MongoDB ODM

I have a 2d index on a coordinates property of my document. Using the mongo shell, I can query the collection like this;
db.adverts.find({coordinates:{$near:[20,40]}})
And that returns the following results, as expected;
{ "_id" : ObjectId("4fddac51352de93903000000"), "title" : "dummy #3", "coordinates" : { "longitude" : 22, "latitude" : 31 } }
{ "_id" : ObjectId("4fddac48352de95105000000"), "title" : "dummy #3", "coordinates" : { "longitude" : 20, "latitude" : 30 } }
{ "_id" : ObjectId("4fddaca4352de93703000000"), "title" : "dummy #3", "coordinates" : { "longitude" : 31, "latitude" : 22 } }
{ "_id" : ObjectId("4fdda6a2352de90a03000000"), "title" : "dummy title", "created" : ISODate("2012-06-17T09:42:58Z"), "coordinates" : { "longitude" : 54.1234, "latitude" : -1.234 } }
{ "_id" : ObjectId("4fdda6d8352de9c004000000"), "title" : "dummy title #2", "created" : ISODate("2012-06-17T09:43:52Z"), "coordinates" : { "longitude" : 54.34, "latitude" : -1.124 } }
However, using Doctrine as per the documentation to query the exact same collection, I get no results e.g.
$adverts = $dm->createQueryBuilder('Advert')
->field('coordinates')->near(20, 40)
->getQuery()
->execute();
$adverts->count(); // => 0
My advert yaml looks like this;
Advert:
type: document
collection: adverts
fields:
id:
id: true
title:
type: string
content:
type: string
created:
type: date
updated:
type: date
status:
type: int
distance:
type: int
indexes:
coordinates:
keys:
coordinates: 2d
referenceOne:
owner:
targetDocument: User
embedOne:
coordinates:
targetDocument: Coordinates
And the Coordinates document is like this;
Coordinates:
type: embeddedDocument
fields:
longitude:
type: float
latitude:
type: float
Any ideas why using Doctrine's ODM would return zero results on the same query?
UPDATE #1
It looks that there is a problem with Doctrine\MongoDB\Query\Builder::near() L363. The method parameter ignores the second value ($y). So only the first value is being passed to be executed.
There appears to be an implementation issue with the near() method (see https://github.com/doctrine/mongodb/pull/53). To fix my original query, I would need to do the following;
$adverts = $dm->createQueryBuilder('Advert')
->field('coordinates.latitude')->near(20)
->field('coordinates.longitude')->near(40);
$adverts->getQuery()->count(); // => 5
This contradicts the current documentation that implies both x, y coordinates can be passed to Doctrine\MongoDB\Query\Builder::near().
EDIT
To make life easier, I've created a custom repository class to provide a more intuitive solution for this inconsistency;
public function near($longitude, $latitude)
{
$query = $this->createQueryBuilder()
->field('coordinates.longitude')->near((float) $longitude)
->field('coordinates.latitude')->near((float) $latitude)
->getQuery();
return $query;
}