Loopback MongoDB Connector: map properties to field names? - node.js

I'm using Loopback's MongoDB connector to expose a RESTful API to query and update a MongoDB collection.
When I defined the model it didn't let me define property names with spaces in them, so instead of "Gas 93" I had to use "gas93". The example is trivial but affect 9 properties of my collection.
I know you can map properties to table fields with the PostgreSQL connector
"properties": {
"name": {
"type": "String",
"required": false,
"postgresql": {
"columnName": "username",
}
}
I haven't found a way to do the same for MongoDB fieldnames. I have a lot of features in my app using collection fieldNames as they are now, so I'd like to avoid changing them to adapt to loopback.
Is there a way to do this? Documentation doesn't say it but, then again, it doesn't say you can't either.

LoopBack doesn't support property mapping for mongoDB at the moment, only collection names can be customized. We will update the documentation to clarify this.

I have added a pull request to support this:
https://github.com/strongloop/loopback-connector-mongodb/pull/189

Related

Azure Search with documentDB does not find data

It's the first time that i'm using Azure Search. I follewed the example with the generated dataset. Now I want to implement Azure search on my database.
This is an example of an item of the collection I want to index.
{
"_id" : "Watch",
"name" : "Watch",
"cloudProvider" : "azure",
"channel" : "C6SELFQMD",
"services" : [
"azure-backup",
"azure-data-lake-analytics",
"backup",
"blobstorage",
"site-recovery",
"storage"
],
"__v" : 0
}
Azure search itself doesn't even detect the fields.
This are the steps i'm doing:
If I add the fields manually it returns useless data. Does somebody know why this is happening? I do only have 2 items in my collection at the moment but I don't think that this is the problem?
UPDATE:
So the problem is that I've an underscore before my id ("_id"). Now I'm trying to use fieldMappings to solve this issue. But the api's response is:
{
"error": {
"code": "",
"message": "Data source does not contain column '_id', which is required because it maps to the document key field 'id' in the index 'index'. Ensure that the '_id' column is present in the data source, or add a field mapping that maps one of the existing column names to 'id'."
}
}
Azure Search currently does not support Cosmos DB Table API accounts, as seems to be the case here.
If you want to see Table API supported by Azure Search, please vote for Azure Search should be able to index Cosmos DB Table API collections to help us prioritize that work.

How To Retrieve Custom Columns For DriveItems in MS Graph

I'm trying to use the Graph API to retrieve a hierarchy of files in a Sharepoint document library. Since document libraries are stored in "drives" (is it technically correct to call it OneDrive?), I'm using the /drives endpoint to fetch a list of files, like this:
https://graph.microsoft.com/beta/drives/{driveid}/root/children
I would like to get information from some of the custom columns that exist when viewing these items through Sharepoint. Using ?expand=fields doesn't work because fields only exists in listItem object of the /sites endpoint, not in the driveItem object of /drives endpoint. If I try obtaining the listItem from a single driveItem (traversing the Graph from OneDrive to Sharepoint), and then expanding the fields, like
https://graph.microsoft.com/beta/drives/{driveid}/items/{driveItemId}/listItem?expand=fields
this retrieves built-in columns (Author, DocIcon, and some others) but doesn't seem to retrieve the custom columns.
I've also tried getting the list of files from the /sites endpoint, and using ?expand=fields will get the custom columns, but it gets every file from every subfolder, rather than the current folder path. But I feel that deserves its own SO question.
Is it possible to retrieve custom column information from driveItems?
I spent a lot of time digging around with the different syntax possibilities and was finally able to get custom library properties using this query format. This is the only one that has produced my custom/user-defined fields for a document library.
https://graph.microsoft.com/v1.0/drives/insert_drive_id_here/root/children?expand=listItem
Shortened result:
{
"#odata.context": "...",
"value": [
{
"#microsoft.graph.downloadUrl": "...",
"listItem#odata.context": "...",
"listItem": {
"#odata.etag": "...",
"fields#odata.context": "...",
"fields": {
"#odata.etag": "...",
"Title": "...",
"Other_Custom_Property": "..."
}
}
}
]
}
I did some testing. What SHOULD work is:
https://graph.microsoft.com/beta/drives/{driveid}/root/children?$select=id,MyCustomColumnName
However, when I did that, it just returned that id field. In my opinion, that is a bug in the graph because this same type of query does work in the SharePoint REST api.
If this helps, you can accomplish this by using the SharePoint REST api. Your endpoint query would be something like:
https://{yoursite}.sharepoint.com/sites/{sitename}/_api/web/lists/(' {DocumentLibraryID}')/items?$select=id,MyCustomColumnName
There are other ways to do the same query.
Try the list endpoint then expand driveItem and fields. You now have both custom column fields and drive item fields.
/beta/sites/[site-id]/lists/[list-id]/items?expand=driveitem,fields&filter=(fields/customColumn eq 'someValue')

How to build search with facetting over unknown/unspecified set of attributes/properties?

I'm working on a product search engine with a big set of undefined products which is constantly growing. Each product has different attributes and at this time they're saved in an array of string key-value pairs like this:
"attributes": [
{
"key": "Producttype",
"value": "Headphones - 3.5 mm plug"
},
{
"key": "Weight",
"value": "280 g"
},
{
"key": "Soundmode",
"value": "Stereo"
},
....
]
Each product has also a category. I'm using elasticsearch 2.4.x to persist data that i want to search on via spring-data-elasticsearch. It's possible to upgrade to the newest elasticsearch version if needed.
As you can see the attributes are really generic. It's also needed to use nested objects to be able to search on this attributes. I'm also thinking about preprocessing this attributes to a standardized format. For example the "Weight" key might be written in different forms like "Productweight" or "Weight of product". Because there are a lot of attributes and i wouldn't like to create a custom property/field for each one i thought about about mapping only the important ones (like weight) to a custom, own field and to map the other attributes like described above.
Now if someone searches for example "iphone" i would like to show some facettes on the left of the search result page. The facettes should differ if someone searches "Adidas shoes". Is this possible with the given format above using nested objects? Is it possible to build the facettes dynamically regarding to the resultset elasticsearch is returning? E.g. the most common properties which all result products contain should be used to create facettes. Or do i have to persist some predefined filters/facettes on each category? I think that would be too much work and also doesn't work on search results where products can have different categories. What's the best practice to build a search feature with facetting on entities with n different properties that can grow in future?

CouchDB view default options in design document not working

The problem is simple: I have written map functions in a design document of a CouchDB database, which emits something {"_id":doc._id}. Together with include_docs=true query option, I will get the desired results with the linked documents. Because the map functions are designed to work with include_docs=true, I put this option in the design document and make it default:
{...
"options":{"include_docs":true}
...}
However, when I query the view, the results are still those without the linked documents, and I need to specify the option explicitly in the query. I also tried to pu other query option (e.g. limit=200) into the design document, they did not work either.
I am using CouchDB 1.5, and cannot find any discussion, issue or bug regarding this. Does anyone have any idea? Thanks in advanced!
Edit: I have reported the issue in Apache, and I am told that the statement about this was removed.
_design/ddoc/options cannot do that.
According to couchdb's docs, a design doc's options object properties only affect view indexing, not view querying. (The only two settings being local_seq and include_design).
_design/ddoc/rewrites can!
If you want to set query options server side, you can do so by specifying a rewrites array in your design document.
Let's say you want to expose a query to _view/myview that has include_docs set to true, you add the following rewrites array to your design document:
{ "_id": "_design/myddoc"
, "views": { "myview": { "map": "function(doc) { ... }" } }
, "rewrites":
[ { "from": "allmyviews/myview"
, "to": "_view/myview"
, "query":
{ "include_docs": "true"
}
}
]
}
Now, when you request http://localhost:5984/mydb/_design/myddoc/_rewrite/allmyviews/myview without the include_docs parameter, couchdb will respond as if you had included it.

couchdb match multiple inconsistent keys

Considering the following two documents:
{
"_id": "a6b8d3d7e2d61c97f4285220c103abca",
"_rev": "7-ad8c3eaaab2d4abfa01abe36a74da171",
"File":"/store/document/scan_bgd123.jpg",
"Commend": "Describes a person",
"DateAdded": "2014-07-17T14:13:00Z",
"Name": "Joe",
"LastName": "Soap",
"Height": "192cm",
"Age": "25"
}
{
"_id": "a6b8d3d7e2d61c97f4285220c103c4a9",
"_rev": "1-f43410cb2fe51bfa13dfcedd560f9511",
"File":"/store/document/scan_adf123.jpg",
"Comment": "Describes a car",
"Make": "Ford",
"Year": "2011",
"Model": "Focus",
"Color": "Blue"
}
How would I find a document based on multiple criteria, say for example "Make"="Ford" and "Color"="Blue". I realize I need a view for this, but I don't know what the key is going to be, and as you can see from the two documents, the key/value pairs aren't consistent. The only consistent item will be the "File" key.
I'm attempting to create couchDB database that will store the location of files, but tagged with Key/Value pairs.
EDIT:
Perhaps I should reconsider my data structure. modify it slightly?
{
"_id": "a6b8d3d7e2d61c97f4285220c103c4a9",
"_rev": "1-f43410cb2fe51bfa13dfcedd560f9511",
"File": "/store/document/scan_adf123.jpg",
"Tags": {
"Comment": "Describes a car",
"Make": "Ford",
"Year": "2011",
"Model": "Focus",
"Color": "Blue"
}
}
So, I need to find by the Key>Value pair in the tag or any number of Key>Value pairs to filter which document I want. The problem here is, I want to tag objects with a key>value pair. These tags could be very different per view, so the next document will have a whole diff set of Key>Value pairs.
Couchdb supports flexible schema. There is no need for the documents to be consistent for them to be query-able. The view for your scenario is pretty straightforward. Here is the map function that should do the trick.
function(doc){
if(doc.Make&&doc.Color)
emit([doc.Make,doc.Color],null);
}
This gives you a view which you can then query like
/view-name/key=["Ford","Blue"]&include_docs=true
This should give you the desired result.
Edit based on comment
For that you will need two separate views. Every view in couchdb is designed to fulfil a specific query need. This means that you have to think about access strategy of your data. It is a lot more work on your part initially but for the trouble you are rewarded with data that is indexed and has very fast access times.
So to answer your question directly. Create two views. One for Make like we have already done and other for Name like
function(doc){
if(doc.Name&&doc.LastName)
emit([doc.Name,doc.Name],null);
}
Now the Name view will index only those documents that have name in it. Where as Make view will index those documents that have make in it.
What happens when a requirement comes in future for which you don't have a query?
You can try a few things.
This is probably the easiest solution. Use couchdb-lucene for your dynamic queries. In this case your architecture will be like couchdb views for queries that you know your application would need. Lucene index for queries that you don't know you might need. So for instance you have indexed name and last name in the in couchdb query. But a requirement arises and you might need to query by age then simply dump the age field in lucene and it will take care of the rest.
Another approach is using the PPP technique where you exploit the fact that creating views is a one time cost and you can create views on less active hours and deploy them in a production service once they are built.
Combine steps 1 and 2! lucene to handle adhoc request while you are building views using the ppp technique.

Resources