The code converts Json object in request payload to string for UDT. We debugged and found the issue with Cassandra.prototype.create function in loopback-connector-cassandra/lib/cassandra.js.
LOGS:
Payload object:
{
id: 'c',
name: 'otlsgy4',
phone: '88774622572',
address: {
street: 'Rajpur Road',
city: 'Dehradun',
state_or_province: 'Uttarakhand',
postal_code: '248001',
country: 'India'
}
}
Insert Query by loopback:
INSERT INTO "hotels" ("id","name","phone","address")
VALUES(?,?,?,?)
[
'c',
'otlsgy4',
'88774622572',
'{
"street":"Rajpur Road",
"city":"Dehradun",
"state_or_province":"Uttarakhand",
"postal_code":"248001",
"country":"India"
}'
]
Expected Result:
INSERT INTO "hotels" ("id","name","phone","address")
VALUES(?,?,?,?)
[
'c',
'otlsgy4',
'88774622572',
{
"street":"Rajpur Road",
"city":"Dehradun",
"state_or_province":"Uttarakhand",
"postal_code":"248001",
"country":"India"
}
]
Link to the repository:
https://github.com/nishankpathak/cassandrademo
Related
In official documentations, it's already shown how to do that. Below, an example that working fine:
Example: 1
LET documents = [
{ name: 'Doc 1', value: 111, description: 'description 111' },
{ name: 'Doc 2', value: 222, description: 'description 2' },
{ name: 'Doc 3', value: 333, description: 'description 3' }
]
FOR doc IN documents
UPSERT { name: doc.name, description: doc.description }
INSERT doc
UPDATE doc
IN MyCollection
But, I want to check different multiple keys for each document on UPSERT, like:
Example: 2
LET documents = [
{ name: 'Doc 1', value: 777, description: 'description 111' },
{ name: 'Doc 2', value: 888, description: 'description 2' },
{ name: 'Doc 3', value: 999, description: 'description 3' }
]
FOR doc IN documents
UPSERT {
{ name: doc.name, description: doc.description },
{ value: doc.value, description: doc.description },
{ name: doc.name, value: doc.value }
}
INSERT doc
UPDATE doc
IN MyCollection
Or, any other other way (using filter or something). I had tried but nothing works
If I understand your problem, you would want to update a document, if there's an existing one with at least 2 fields matching, otherwise insert it as new.
UPSERT won't be able to do that. It can only do one match. So a subquery is necessary. In the solution below, I ran a query to find the key of the first document that matches at least 2 fields. If there's no such document then it will return null.
Then the UPSERT can work by matching the _key to that.
LET documents = [
{ name: 'Doc 1', value: 777, description: 'description 111' },
{ name: 'Doc 2', value: 888, description: 'description 2' },
{ name: 'Doc 3', value: 999, description: 'description 3' }
]
FOR doc IN documents
LET matchKey= FIRST(
FOR rec IN MyCollection
FILTER (rec.name==doc.name) + (rec.value==doc.value) + (rec.description==doc.description) > 1
LIMIT 1
RETURN rec._key
)
UPSERT {_key:matchKey}
INSERT doc
UPDATE doc
IN MyCollection
Note: There's a trick with adding booleans together which works because true will be converted to 1, while false is zero. You can write it out explicitly like this: (rec.name==doc.name?1:0)
While this will work for you it's not a very effective solution. Actually there's no effective one in this case because all the existing documents need to be scoured through to find a matching one, for each document to be added/updated. I'm not sure what kind of problem you are trying to solve with this, but it might be better to re-think your design so that the matching condition could be more simple.
When I query from collection in MongoDB and it has results:
[ { details:
[ { owner: '57f52829bcc705bb1c37d611',
nameprd: 'fsfsdaf',
price: 15000000,
descrice: 'sfsdfsdaf',
number: 4,
dateOff: '2016-06-12T17:00:00.000Z',
_csrf: 'CPlxeLpq-vYfTTWTgSpR6bsyapbDVgDCKzTc',
image: 'samsung-galaxy-note-7.png',
createdAt: '2016-10-06T16:43:11.109Z',
updatedAt: '2016-10-06T16:43:13.061Z',
id: '57f67f1f7ab99e5824652208' } ],
name: 'Máy tính bảng',
_csrf: 'Ze6OhtgL-2hZvG7TuP9NO4fjY90rA7x46bWA',
createdAt: '2016-10-05T16:19:53.331Z',
updatedAt: '2016-10-06T16:43:13.021Z',
id: '57f52829bcc705bb1c37d611' },
]
Now, how to get value which called details in this result.
Thanks.
You should add the query the following syntax: ,{'details':1}
For example:
If that is the original query:
db.person.find({'name':'joe'})
Than the following query returns only the details value of the query:
db.person.find({'name':'joe'},{'details':1})
The addition of the ,{'details':1} means that you want to get only the data for the details. It is uses as a filter to the extensive query.
I'm looking to $push something into a nested array, of which the parent array matches a simple property condition:
Here's how my document looks:
{
name: "Foo",
boardBucket: {
currentBoardId: 1234,
items: [ <- looking to push into `boardItems` of an `item` in this Array
{
boardId: 1234, <- that has `boardId: 1234`
boardItems: [ "barItem", "deyItem" ] <- Final Array I want to push to
}
]
}
}
So I'd like to push "fooItem" in boardItems of item that has boardId: 1234
Option 1: I can use dot notation and access by index
I can certainly do a $push by using dot.notation which uses the index of the item like so:
this.update({ '$push': {"boardBucket.items.0.boardItems": "fooItem" } });
But what if I don't know the index?
How can I push into boardItems of item with boardId: 1234 without using the indices (using the boardId instead)?
Note:
I'm using mongoose as the db driver
I'd like to avoid using mongoose's save() cause it tends to be buggy + it seems to keep a copy of the object locally which i'd like to avoid
Just direct update() mongo queries are what I'm after
I'd certainly like to avoid any type of whole-document fetching to perform this update as my documents are huge in size
I think this should do the trick:
this.update(
{"boardBucket.items": {$elemMatch: { boardId: "1234"}}},
{'$push': {"boardBucket.items.boardItems": "fooItem" }}
);
(Sorry for not sampling in the first place, was on a rush then)
db.myDb.insert({
name: "Foo",
boardBucket: {
currentBoardId: 1234,
items: [
{
boardId: 1234,
boardItems: [ "barItem", "deyItem" ]
},
{
boardId: 1235,
boardItems: [ "dontPushToThisOne" ]
}
]
}
});
db.myDb.insert({
name: "Foo2",
boardBucket: {
currentBoardId: 1236,
items: [
{
boardId: 1236,
boardItems: [ "dontPushToThisOne" ]
}
]
}
});
db.myDb.update(
{ "boardBucket.currentBoardId":1234,
"boardBucket.items.boardId":1234},
{ "$push" : {"boardBucket.items.$.boardItems":"fooItem"} }, {multi:1} );
I have collection structure like this.
application_data: {
name : A,
site : B,
location : [
{ key1 : value1, key2 : value2},
{ key3 : value3, key4 : value4}
]
}
Now I want to add a another array to "location" as a sub document so that my location becomes
location : [
{ key1 : value1, key2 : value2},
{ key3 : value3, key4 : value4, key5 :[{subkey1:subvalue1, subkey2:subvalue2}]}
]
I tried $push & $addToSet which did not help me. Can somebody help me?
Helpful if you explain an example using nodejs.
What you'r actually trying to do is to add new field to an existing subdocument. You can do it using $set and positional operator $:
db.applications.update({
name: 'A', // querying for parent document
'location.key3': 'value3' // querying for an exact subdocument to add new field to
}, {
$set: {
'location.$.key5': [{
subkey1: 'subvalue1',
subkey2: 'subvalue2'
}]
}
})
You can achieve the same result using $push or $addToSet, which is better if you want to add more than one subsubdocument to 'location.key5':
db.applications.update({
name: 'A',
'location.key3': 'value3'
}, {
$push: {
'location.$.key5': {
subkey1: 'subvalue1',
subkey2: 'subvalue2'
}
}
})
or
db.applications.update({
name: 'A',
'location.key3': 'value3'
}, {
$addToSet: {
'location.$.key5': {
subkey1: 'subvalue1',
subkey2: 'subvalue2'
}
}
})
See Update Documents in an Array for more info.
When I try to find all members within 50km of Salt Lake City, Utah from the Mongo shell I get the error:
error: {
"$err" : "point not in interval of [ -180, 180 ] :: caused by :: { 0: 0.0, 1: 50000.0 }",
"code" : 16433
}
Here is the query I am running:
db.members.find(
{ 'geo.point' :
{ $near :
{
$geometry : {
type : "Point" ,
coordinates : [ 111.000 , 40.000 ]
},
$maxDistance : 50000
}
}
}
)
Member schema is like this:
var memberSchema = mongoose.Schema({
name: {
first: {type:String, default:''},
last: {type:String, default:''},
},
geo: {
latitude: {type:String, default:''},
longitude: {type:String, default:''},
country: {type:String, default:''},
state: {type:String, default:''},
place: {type:String, default:''},
zip: {type:String, default:''},
point: {type: [Number], index: '2d'}
}
});
Member object in DB looks like this:
{
"_id" : ObjectId("xxxxxxxxxxxxxxxxxxx"),
"name": {
"first": "Thom",
"last": "Allen"
},
"geo" : {
"point" : [ -111.8833, 40.7500 ],
"zip" : "84115",
"state" : "UT",
"country" : "US",
"longitude" : "-111.8833",
"latitude" : "40.7500"
}
}
Is it possible that my fields are not stored in the correct format? If I change 50000 to anything below 180 it will work, but that is not how it should function according to the docs here:
http://docs.mongodb.org/manual/reference/operator/query/near/
** Just a heads up, the proper mongo location array IS in fact [longitude, latitude].
A few things. First, I think your query is off - you are querying for coordinates : [ 111.000 , 40.000 ] and it should be coordinates : [ -111.000 , 40.000 ]
Second, the example data point your provide [ -111.8833, 40.7500 ] is more than 50 km from your corrected query point, it's actually about 122 km (test it here: http://andrew.hedges.name/experiments/haversine/ )
So, correcting for those two issues if I store the data in mongodb as you have stored it I can do the following:
1) create the correct index:
db.members.ensureIndex({ "geo.point": "2dsphere" })
2) run this query:
db.members.find({ 'geo.point':
{$geoWithin:
{$centerSphere: [[ -111.000 , 40.000 ], 113/6371]}
}
} )
Note that I've divided 113 km/ 6371 which gives you radians which is what is required for this specific query.
Try it yourself. In general you will be better off if you can store things in the future using GeoJSON but with your existing schema and the above index and query I'm able to get the correct results.
What you have in your data is the format for legacy co-ordinate pairs but you are trying to query using the GeoJSON syntax.
The only valid index form for legacy co-ordinate pairs is a "2d" index, so if you have created a "2d sphere" index that will not work. So you need to remove any "2d sphere" index and create a "2d" index as follows:
db.members.ensureIndex({ "geo.point": "2d" })
If you actually intend to use the GeoJSON form and "2dsphere" index type, then you need the data to support it, for example:
{
"loc" : {
"type" : "Point",
"coordinates" : [ 3, 6 ]
}
}
So it needs that underlying structure of "type" and "coordinates" in order to use this index type and query form.