Using MongoDB: 6.0.4
Using Mongosh: 1.4.1
I inserted a book and a publisher (dbRef) with mongosh.
# insert publisher
publisher_id = ObjectId()
db.publishers.insert_one({
'_id': publisher_id,
'title': 'XXX',
'website': 'https://xxxxxxx.com',
})
# insert books
db.books.insert_one({
'title': 'Good book',
'author': 'Someone',
'publishers': [
{
'$ref': 'publishers',
'$id': publisher_id,
},
],
})
Then run the following commands with mongosh.
> var book = db.books.findOne({title:'Good book'})
> var dbRef = book.publishers[0]
> dbRef
DBRef("publishers", ObjectId("..."))
According to the link below, I think I can access $id and $ref of the dbRef object, but I got empty lines. How can I access $id and $ref with mongosh?
> dbRef.$id
// empty line
> dbRef.$ref
// empty line
> dbRef.collection
publishers
> JSON.stringify(dbRef)
{"$ref":"publishers","$id":"..."}
How to show data from 2 collections in Mongodb with DBRef
UPDATE
For newer version of mongosh,
> dbRef.oid
ObjectId("...")
> dbRef.collection
publishers
For older version of mongosh,
> dbRef.toJSON().$id
ObjectId("...")
> dbRef.toJSON().$ref
publishers
DBRef is a separate data type: https://mongodb.github.io/node-mongodb-native/3.6/api/DBRef.html
new DBRef(namespace, oid, db)
Name
Type
Description
namespace
string
the collection name
oid
ObjectID
the reference ObjectID
db
string
optional db name, if omitted the reference is local to the current db
Try dbRef.oid
Related
I migrated my database from Sql Server to MongoDB
I want to Join existing customer Table with contact Table .
Customer have multiple contacts . I tried whereRaw lookup
customer collection
{
"_id": 77,
"custid": 93
}
Contact Collection
{"_id":77,"contactid":77,"custid":93,"firstname":"Christy ","lastname":"Lambright" }
{"_id":79,"contactid":79, "custid":93,"firstname":"Marlys ","lastname":"Barry" }
Customer Modal
class custt extends Model
{
use Notifiable;
protected $primaryKey = 'id';
}
Contact Modal
class contact extends Model
{
use Notifiable;
protected $primaryKey = 'id';
In Controller
$cnt = DB::collection("custts")->raw(function($collection)
{
$more_where = [];
$more_where[]['$lookup'] = array(
'from' => 'contacts',
'localField' => 'custid',
'foreignField' => 'custid',
'as' => 'country',
);
return $collection->aggregate($more_where);
});
Error comes --
Empty Results
I tried Lots of options for hasMany and belongstoMany . Not working ...
please suggest
ok , finally found it working
source - https://github.com/jenssegers/laravel-mongodb/issues/841
$cnt = custt::raw(function($collection)
{
return $collection->aggregate(
[[
'$lookup' => [
'as'=>'info',
'from'=>'contacts',
'foreignField'=>'custid',
'localField'=>'custid'
]
]]
);
});
Building an app using React Native (for iOS) using AWS Amplify
I want to do something seemingly so simple, but i am a bit lost as to how to do it: I have a table with user information already in it. Here's the Schema:
type Users #model {
id: ID!
userName: String
firstname: String
weblink: String
email: String
mobileNum: String
.
.
.
}
//**Here's my current Query.js**
export const getUsers = `query GetUsers($id: ID!) {
getUsers(id: $id) {
id
userName
firstname
weblink
email
.
.
.
}
}
`;
This table is populated in DynamoDB when i check my AWS console. What i need is to be able to get the id from the table using the userName (not vice versa). The id is generated when i createUser() and it's used throughout my app to get all my user's information. However when a user signs in on a new phone, this id isn't available anymore. So when they sign in via Cognito, i do know the userName and all i need to do is retrieve this id. Because there's only one unique userName, it should only return one id
Here's what i'm thinking so far: use a GSI (global secondary index). So change my schema to:
type Users #model
#key(
name: "ByUsername"
fields: ["userName"]
queryField: "getIdFromUserName"
)
{
id: ID!
userName: String
firstname: String
weblink: String
email: String
mobileNum: String
.
.
.
}
Then call in my app:
const data = await API.graphql(graphqlOperation(getIdFromUserName, { userName }));
5 questions:
1) Is there a simpler way than GSI?
2) Is that how you add the GSI? Or is it more robust to do it in the AWS console?
3) What should my Query.js then look like?
4) Do i need to make a custom resolver, or is this sufficient?
5) Am i missing anything else, or can i just
amplify push ?
//11/04/2020
//Resolver
## [Start] Prepare DynamoDB PutItem Request. **
$util.qr($context.args.input.put("createdAt", $util.defaultIfNull($ctx.args.input.createdAt, $util.time.nowISO8601())))
$util.qr($context.args.input.put("updatedAt", $util.defaultIfNull($ctx.args.input.updatedAt, $util.time.nowISO8601())))
$util.qr($context.args.input.put("__typename", "Users"))
#set( $condition = {
"expression": "attribute_not_exists(#id)",
"expressionNames": {
"#id": "id"
}
} )
#if( $context.args.condition )
#set( $condition.expressionValues = {} )
#set( $conditionFilterExpressions = $util.parseJson($util.transform.toDynamoDBConditionExpression($context.args.condition)) )
$util.qr($condition.put("expression", "($condition.expression) AND $conditionFilterExpressions.expression"))
$util.qr($condition.expressionNames.putAll($conditionFilterExpressions.expressionNames))
$util.qr($condition.expressionValues.putAll($conditionFilterExpressions.expressionValues))
#end
#if( $condition.expressionValues && $condition.expressionValues.size() == 0 )
#set( $condition = {
"expression": $condition.expression,
"expressionNames": $condition.expressionNames
} )
#end
{
"version": "2017-02-28",
"operation": "PutItem",
"key": #if( $modelObjectKey ) $util.toJson($modelObjectKey) #else {
"id": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.args.input.id, $util.autoId()))
} #end,
"attributeValues": $util.dynamodb.toMapValuesJson($context.args.input),
"condition": $util.toJson($condition)
}
## [End] Prepare DynamoDB PutItem Request. **
1) You dont need to create GSI (global secondary index).
2) You can update your createUser resolver, instead of using $util.autoId() you can pass $ctx.args.input.userName as id
I have mysql db with column that called "info", this is json column.
I have there this json:
{
"pizza":{
"sugar":"yes",
"calorie":"100",
"protein":"no"
},
"hamburger":{
"sugar":"no",
"calorie":"120",
"protein":"yes"
}
}
when I want to update for example the calorie of the pizza there is no problem:
DB::table('food')->where('id', '=', '1')
->update(array('info->pizza->calorie' => '90'));
then in the db i have:
{
"pizza":{
"sugar":"yes",
"calorie":"90",
"protein":"no"
},
"hamburger":{
"sugar":"no",
"calorie":"120",
"protein":"yes"
}
}
but when i want to add some food, for example chocolate:
DB::table('food')->where('id', '=', '1')
->update(array('info->chocolate->calorie' => '10'));
nothing happened.
In which way I can do that? thanks!
You can't update non-existing keys for json columns in MySQL table. Look at this post to better understand the reason why.
To solve this problem, your best bet is to retrieve the column json data, decode it, insert new object entry, encode it again and finally update the table with the new json data.
$food = DB::table('food')->where('id', '=', '1')->first();
$info = json_decode($food->info);
$info->chocolate = (object)["calorie"=>"10"];
DB::table('food')->where('id', '=', '1')
->update(['info' => json_encode($info)]);
Which version of Laravel are you using? I'm able to set new keys in JSON cast columns using both 5.7 and 5.8:
User Model:
protected $casts = [
'phone_numbers' => 'json',
];
Updating:
User::first()->phone_numbers;
[
'mobile' => '0000000000',
]
User::first()->update(['phone_numbers->office'] => '9999999999']);
User::first()->phone_numbers;
[
'mobile' => '0000000000',
'office' => '9999999999',
]
Updating nested values:
User::first()->update(['phone_numbers->office->ext'] => '100']);
User::first()->phone_numbers;
[
'mobile' => '0000000000',
'office' => [
'ext' => '100',
],
]
Edit: You don't happen to have $fillable set for the info column, do you? If so, I believe you'll have to specify each individual property for mass-assignment:
protected $fillable = [
'info->chocolate',
];
You can test it quickly by removing it from $fillable and setting $guarded to an empty array (temporarily):
protected $guarded = [];
I know this is the exact answer, as 2 queries have to be performed on DB. But this is a workaround.
$food = DB::table('food')->where('id', '=', '1')->first();
$info = json_decode($food->info, true);
$info['chocolate']['calorie] = 10;
$food->info = json_encode(json_encode($info), JSON_FORCE_OBJECT);
$food->save();
I need to update the database table according to the edited data.
controller
public function update(Request $request)
{
$subscriptionplan = SubscriptionPlan::find($request->id);
$subscriptionplan->update($request->all());
return back();
}
But nothing happens when I submit the form. When I use dd($request->all()); at the beginning of the function, it correctly shows the edited data as follows.
array:10 [▼
"_method" => "patch"
"_token" => "gOCL4dK6TfIgs75wV87RdHpFZkD7rBpaJBxJbLHF"
"editname" => "SUP_EVA_001"
"editdesc" => "des"
"editprice" => "1000.050"
"editlimit" => "1"
"editperunit" => "20.000"
"editexceedunit" => "30.000"
"productid" => "1"
"id" => "1"
]
But database has not been updated.
My table name is Table: subscription_plans and model is SubscriptionPlan
These are the table columns:
protected $fillable = [
'name',
'description',
'price',
'usage_limit',
'charge_per_unit',
'charge_per_unit_exceed',
'is_limit_exceed_considered',
'product_id'
];
Any idea on how to solve it or what I have done wrong?
If your solution did not work, try the 1by1 like this.
public function update(Request $request)
{
$subscriptionplan = SubscriptionPlan::find($request->id);
$subscriptionplan->_method = $request->_method;
$subscriptionplan->_token = $request->_token;
$subscriptionplan->editname = $request->editname;
$subscriptionplan->editdesc = $request->editdesc;
$subscriptionplan->editprice = $request->editprice;
$subscriptionplan->editlimit = $request->editlimit;
$subscriptionplan->editperunit = $request->editperunit;
$subscriptionplan->editexceedunit = $request->editexceedunit;
$subscriptionplan->productid = $request->productid;
$subscriptionplan->save();
return back();
}
In order for Laravel to automatically fill the model attributes, the indexes of the array passed to the fill method must correspond to your model attributes names.
Also, instead of
$subscriptionplan->update($request->all());
Use
$subscriptionplan->fill($request->all());
Then save the subscription plan with $subscriptionplan->save();
I want to add a "field collection" dynamically. But I'm not familiar with Field API or Entity API. New Entity API in Drupal is very poorly documented.
Here is my code, until now:
$node = node_load(1);
$field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_book_text'));
$field_collection_item->setHostEntity('node', $node);
// Adding fields to field_collection
$field_collection_item.save();
"Field Collection" module use function "entity_form_submit_build_entity" which I cannot use because there is no form in my case.
I would appreciate if you can tell me how can I add fields?
Based on some code I used in a live project:
// Create and save research field collection for node.
$field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_article_references'));
$field_collection_item->setHostEntity('node', $node);
$field_collection_item->field_reference_text[$node->language][]['value'] = 'ABCD';
$field_collection_item->field_reference_link[$node->language][]['value'] = 'link-val';
$field_collection_item->field_reference_order[$node->language][]['value'] = 1;
$field_collection_item->save();
Anyone using the above code samples should consider using the entity_metadata_wrapper function from the Entity API to set the values of fields on an entity instead of using an assignment operator. So, the code from the "more complete example" above would be:
if ($node->field_collection[LANGUAGE_NONE][0]) {
// update
$fc_item = reset(entity_load('field_collection_item', array($node->field_collection[LANGUAGE_NONE][0]['value'])));
}
else {
// create
$fc_item = entity_create('field_collection_item', array('field_name' => 'field_collection'));
$fc_item->setHostEntity('node', $node);
}
// Use the Entity API to "wrap" the field collection entity and make CRUD on the
// entity easier
$fc_wrapper = entity_metadata_wrapper('field_collection_item', $fc_item);
// ... set some values ...
$fc_wrapper->field_terms->set('lars-schroeter.com');
// save the wrapper and the node
// Note that the "true" is required due to a bug as of this time
$fc_wrapper->save(true);
node_save($node);
A more complete example:
if ($node->field_collection[LANGUAGE_NONE][0]) {
// update
$fc_item = reset(entity_load('field_collection_item', array($node->field_collection[LANGUAGE_NONE][0]['value'])));
}
else {
// create
$fc_item = entity_create('field_collection_item', array('field_name' => 'field_collection'));
$fc_item->setHostEntity('node', $node);
}
// ... set some values ...
$fc_item->field_terms[LANGUAGE_NONE][0]['value'] = 'lars-schroeter.com';
// save node and field-collection
$node->field_collection[LANGUAGE_NONE][0] = array('entity' => $fc_item);
node_save($node);
You don't need to call node_save($node) when using entity_metadata_wrapper. It will ensure that only the entity's data and the reference to the host are saved without triggering any node_save, which is a good performance boost.
However, you would still need node_save() if you have any node_save-triggered actions that use this field collection (e.g. a rule that sends emails when the node is edited).
use the wrappers, they are your friend:
// Create an Entity
$e = entity_create('node', array('type' => 'CONTENT_TYPE'));
// Specify the author.
$e->uid = 1;
// Create a Entity Wrapper of that new Entity
$entity = entity_metadata_wrapper('node',$e);
// Specify the title
$entity->title = 'Test node';
// Add field data... SO MUCH BETTER!
$entity->field_FIELD_NAME->set(1111);
// Save the node.
$entity->save();
You can find Entity API documented in Entity API Tutorial at Drupal.org.
There you can find some useful examples, especially check for Entity metadata wrappers page.
Here is example based on your variables:
$node = node_load(1);
$field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_book_text')); // field_book_text is field collection
$field_collection_item->setHostEntity('node', $node);
$cwrapper = entity_metadata_wrapper('field_collection_item', $field_collection_item);
// Adding fields to field_collection
$cwrapper->field_foo_text->set("value");
$cwrapper->field_foo_multitext->set(array("value1", "value2"));
$cwrapper.save();
Here is another example using field collections from above docs page:
<?php
// Populate the fields.
$ewrapper = entity_metadata_wrapper('node', $node);
$ewrapper->field_lead_contact_name->set($contact_name);
$ewrapper->field_lead_contact_phone->set($contact_phone);
$ewrapper->field_lead_contact_email->set($contact_email);
// Create the collection entity and set it's "host".
$collection = entity_create('field_collection_item', array('field_name' => 'field_facilities_requested'));
$collection->setHostEntity('node', $node);
// Now define the collection parameters.
$cwrapper = entity_metadata_wrapper('field_collection_item', $collection);
$cwrapper->field_facility->set(intval($offset));
$cwrapper->save();
// Save.
$ewrapper->save();
?>
Here is more advanced example of mine which for given entity it loads taxonomy term references from field_rs_property_features, then for each secondary term which has a parent term, adds its term name and its parent term name into field_feed_characteristics_value by grouping them together into title (parent) and value (child). It's probably more difficult to explain without seeing the code. So here it is:
/**
* Function to set taxonomy term names based on term references for given entity.
*/
function MYMODULE_refresh_property_characteristics(&$entity, $save = FALSE) {
try {
$w_node = entity_metadata_wrapper('node', $entity);
$collections = array();
foreach ($w_node->field_rs_property_features->getIterator() as $delta => $term_wrapper) {
if ($term_wrapper->parent->count() > 0) {
$name = $term_wrapper->name->value();
$pname = $term_wrapper->parent->get(0)->name->value();
if (array_key_exists($pname, $collections)) {
$collections[$pname]->field_feed_characteristics_value[] = $name;
} else {
// Create the collection entity, set field values and set it's "host".
$field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_feed_characteristics'));
$field_collection_item->setHostEntity('node', $w_node->value());
$collections[$pname] = entity_metadata_wrapper('field_collection_item', $field_collection_item);
$collections[$pname]->field_feed_characteristics_title = $pname;
$collections[$pname]->field_feed_characteristics_value = array($name);
}
}
}
if ($save) {
$w_node->save();
}
} catch (Exception $e) {
drupal_set_message(t('Error setting values for field collection: #title, message: #error.',
array('#title' => $w_node->title->value(), '#error' => $e->getMessage())), 'error');
watchdog_exception('MYMODULE', $e);
return FALSE;
}
return TRUE;
}