Couchbase CRUD operations with query language - spring

Im using couchbase 4.0 beta version. And Im successfully able to save the objects into the bucket using rest service. Now I need to access the bucket and do GET, UPDATE and DELETE operations using queries.
This is the my sample object in bucket.
{
"id": "friend$43403778",
"domain": "FRIEND",
"profileId": 43403778,
"screenName": "49ers",
"name": "San Francisco 49ers",
"profileUrl": "http://twitter.com/49ers",
"description": "Official Twitter account of the five-time Super Bowl Champion San Francisco #49ers.",
"friendsCount": 121,
"followersCount": 964650,
"timeZone": "Pacific Time (US & Canada)",
"utcOffset": -25200,
"location": "Santa Clara, CA",
"profileCreated": 1243629277000
}
Now I want to get this object using id. But id value contains special character so my query doesn't works for it. How can I access it???
This is my code snippet which I tried to get this.It doesn't gives me the 300 error code syntax error.
String strQuery = "SELECT * FROM twitter WHERE id=" + id;
Bucket bucket = singletonBucket.getBucket();
QueryResult queryResult = bucket.query(Query.simple(strQuery));
List<QueryRow> result = Collections.emptyList();
if (!queryResult.finalSuccess()) {
log.error("Error occur while retrieving TwitterProfile document for id: {}",id);
String errorStr = "";
for (JsonObject error : queryResult.errors()) {
errorStr = error.toString() + ". ";
log.error("{}", error);
}
throw new DataAccessException(errorStr);
} else {
result = queryResult.allRows();
for(QueryRow row: result){
Object doc = row.value().get(AppConstants.BUCKET_NAME);
TwitterProfile twitterProfile = objectMapper.readValue(doc.toString(), TwitterProfile.class);
twitterProfileList.add(twitterProfile);
}
log.info("Successfully found {} TwitterProfile record for id {}",twitterProfileList.size(), id);
return twitterProfileList.size()>0 ?twitterProfileList.get(0):"";
}
If I tried to get the record using profileId It also doesnt work.
How can I write the simple queries for this bucket.
These are the queries which I tried. Also my bucket name is twitter
String strQuery = "SELECT * FROM twitter WHERE domain=" + AppConstants.DOMAIN_FRIEND;
String strQuery = "DELETE FROM twitter WHERE domain=" + AppConstants.DOMAIN_FRIEND;
Thanks in advance.

When building your query you have to use quotes to indicate your id is a string. Try adding quotes around your id when building your query:
String strQuery = "SELECT * FROM twitter WHERE id='" + id + "'";

Related

get googlesheets cells with name sheet with accents

I try to use the gradle exemple to get googlessheets cells and get error with the tab name with diacritics ("Opérations 2023") because the name is in french.
https://developers.google.com/sheets/api/quickstart/java
the error is below.
{
"code": 400,
"errors": [
{
"domain": "global",
"message": "Unable to parse range: Op%C3%A9rations%202023!A2%3AE2",
"reason": "badRequest"
}
],
"message": "Unable to parse range: Op%C3%A9rations%202023!A2%3AE2",
"status": "INVALID_ARGUMENT"
}
The request is
public static void main(String... args) throws IOException, GeneralSecurityException {
// Build a new authorized API client service.
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
final String spreadsheetId = "ID";
final String range = "Opérations 2023!A2:E2";
Sheets service =
new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();
ValueRange response = service.spreadsheets().values()
.get(spreadsheetId, range)
.execute();
List<List<Object>> values = response.getValues();
if (values == null || values.isEmpty()) {
System.out.println("No data found.");
} else {
System.out.println("Name, Major");
for (List row : values) {
// Print columns A and E, which correspond to indices 0 and 4.
System.out.printf("%s, %s\n", row.get(0), row.get(4));
}
}
}
}
What can I do please ?
I'm writing this answer as a community wiki, since the issue was resolved from the comments section, in order to provide a proper response to the question.
I tested with Sheets API Method: spreadsheets.values.get and I had no issues using it with sheet named "Opérations 2023" so it seems is not issue with the API but character encoding in Java.
I'm not an expert in Java, but while doing research, I found a similar thread and it shows the same error when using Java while doing it with Python it seems to work with no issue.
As a workaround, if the sheet you're aiming to is the first one in your Worksheet, then you can just omit the name of the Sheet and set the range to: "A2:E2", this will aim the default sheet which is the first one in your Worksheet.

In Nest 1.7.1 Delete or DeleteByQuery nothing works

In Nest 1.7.1 Delete or DeleteByQuery nothing works for me.
I am trying to delete below documents:
Article article1 = new Article()
{
Id = 1111,
Title = "Title - Test Elastic Search",
Summary = "Summary - Test Elastic Search",
Body = "Body - Test Elastic Search",
ArticleDate = _dateToday,
Author = new Author() { Id = 100, Name = "Mikey" },
};
Article article2 = new Article()
{
Id = 2222,
Title = "Title - Test Elastic Search",
Summary = "Summary - Test Elastic Search",
Body = "Body - Test Elastic Search",
ArticleDate = _dateToday,
Author = new Author() { Id = 100, Name = "Mikey" },
Published = true
};
I was expecting below queries would delete single document and all documents in an index but no query is deleting.
_elasticClient.Delete(article).Found;
_elasticClient.DeleteByQuery<Article>(q => q.Query(t => t.Term(m => m.OnField(f => f.Id).Value(articleId))))
.Found;
_elasticClient.DeleteByQuery<Article>(q => q.MatchAll()).IsValid;
Please correct me if i am doing anything wrong.
Here's a working example
void Main()
{
var settings = new ConnectionSettings(new Uri("http://localhost:9200"), "articles");
var client = new ElasticClient(settings);
if (client.IndexExists("articles").Exists)
{
client.DeleteIndex("articles");
}
client.CreateIndex("articles", c => c
.AddMapping<Article>(m => m
.MapFromAttributes()
)
);
var today = DateTime.Now.Date;
var article1 = CreateArticle(1111, today);
var article2 = CreateArticle(2222, today);
var article3 = CreateArticle(3333, today);
var article4 = CreateArticle(4444, today);
var bulkRequest = new BulkDescriptor();
bulkRequest.Index<Article>(i => i.Document(article1));
bulkRequest.Index<Article>(i => i.Document(article2));
bulkRequest.Index<Article>(i => i.Document(article3));
bulkRequest.Index<Article>(i => i.Document(article4));
bulkRequest.Refresh();
client.Bulk(bulkRequest);
var searchResponse = client.Search<Article>(q => q.MatchAll());
Console.WriteLine("Documents from search: {0}. Expect 4", searchResponse.Documents.Count());
client.Delete(article1, d => d.Refresh());
searchResponse = client.Search<Article>(q => q.MatchAll());
Console.WriteLine("Documents from search {0}. Expect 3", searchResponse.Documents.Count());
client.Delete(article2, d => d.Refresh());
searchResponse = client.Search<Article>(q => q.MatchAll());
Console.WriteLine("Documents from search {0}. Expect 2", searchResponse.Documents.Count());
client.DeleteByQuery<Article>(q => q.MatchAll());
searchResponse = client.Search<Article>(q => q.MatchAll());
Console.WriteLine("Documents from search {0}. Expect 0", searchResponse.Documents.Count());
}
private Article CreateArticle(int id, DateTime articleDate)
{
return new Article()
{
Id = id,
Title = "Title - Test Elastic Search",
Summary = "Summary - Test Elastic Search",
Body = "Body - Test Elastic Search",
ArticleDate = articleDate,
Author = new Author() { Id = 100, Name = "Mikey" },
Published = true
};
}
public class Article
{
public int Id { get; set;}
public string Title{ get; set;}
public string Summary { get; set;}
public string Body { get; set;}
public DateTime ArticleDate { get; set; }
public Author Author { get; set; }
public bool Published { get; set;}
}
public class Author
{
public int Id { get; set; }
public string Name { get; set;}
}
results in
Documents from search: 4. Expect 4
Documents from search 3. Expect 3
Documents from search 2. Expect 2
Documents from search 0. Expect 0
as expected.
Something to bear in mind is that Elasticsearch is eventually consistent meaning that a document that is indexed does not appear in search results until after a refresh interval (by default, 1 second); Likewise, with a delete query, a document marked for deletion will appear in search results until the refresh interval has elapsed.
A GET request on a given document with a given id will however return the document before the refresh interval.
If you need documents to be searchable (or to not show in search results after deletion), you can refresh the index after an operation as I did with the bulk and delete calls above, using .Refresh(). You might be tempted to call refresh after every operation, however I would recommend using it only when you really need to as it adds overhead to the cluster and called all the time would likely degrade performance.
I got it working finally.
The delete request which is sent via NEST in fiddler is DELETE /articlestest/article/_query and the query which worked in plugin is this DELETE /articlestest/articles/_query ( the document type name was misspelled in the code).That's the reason ,query was not deleting the documents via NEST.And the bad thing is ,it doesn't even complain about the non-existent document type :( It took me a while to found that issue.

How to delete multiple nodes by specific ID using Cypher

I am trying to optimize this cypher query.
I am using neo4j-jdbc
For a given source node and list of target nodes I would like to remove the relationship("follow) between them).
Right now I only found a way to execute them on each transaction:
for example:
source node: 34 and targetNodes: 777
execute:
MATCH (p1:users)-[r:follow]->(p2:users)
WHERE p1.userId='34' and p2.userId='777' and
delete r
java neo4j-jdbc code:
public void deleteNodes(String sourceUserId, Set<String> userIdsList) {
try {
conn = neo4jDataSource.openConnection();
conn.setAutoCommit(false);
newUserDistanceList.forEach(user -> {
try {
this.deleteRelationship(sourceUserId, user.getUserId());
} catch (SQLException e) {
throw new RuntimeException("Error deleting relationship for sourceNode=" + sourceUserId + ", targetNode=" + user.getUserId(), e);
}
});
conn.commit();
} catch (Exception e) {
throw new RuntimeException("Error deleting relationship for sourceNode=" + sourceUserId, e);
} finally {
neo4jDataSource.closeConnection(conn);
}
}
public void createNodeAndSetRelationship(String sourceUserId, String targetUserId) throws SQLException {
String deleteUserStmnt =
"MATCH (p1:users)-[r:follow]->(p2:users) "+
"WHERE p1.userId=~{1} and p2.userId=~{2} and "+
"delete r";
try (final PreparedStatement ps1 = conn.prepareStatement(deleteUserStmnt)) {
ps1.setString(1, sourceUserId);
ps1.setString(2, targetUserId);
ps1.executeQuery();
}
}
How would you optimize this into one query to include it all? is it even possible?
*P.S please add any other notes about this code if you find them helpful.
Response to comments:
I added my nodes this way:
MERGE (p1:C10{userId:'1'})
MERGE (p2:C10{userId:'2'})
MERGE (p3:C10{userId:'3'})
MERGE (p1)-[r1:follow]->(p2)
MERGE (p1)-[t1:follow]->(p3)
When executing the delete query nothing is being deleted:
MATCH (user1:C10 {userId: 1})-[r:follow]->(users:C10) WHERE
users.userId in [3, 2] DELETE r
userId is unique property on each node
Any idea?
Thank you,
ray.
Query
Let's create some data to test that our query will work.
CREATE (user1:User {id: "1"})
CREATE (user2:User {id: "2"})
CREATE (user3:User {id: "3"})
CREATE (user1)-[:FOLLOW]->(user2)
CREATE (user1)-[:FOLLOW]->(user3)
How our data looks right now:
Let's write query to delete :FOLLOW relationship from between user1 and user2 and user3:
MATCH (user1:User {id: "1"})-[r:FOLLOW]->(users:User)
WHERE users.id in ["2", "3"]
DELETE r
Now relationship's are gone:
Good luck :)
Note: this works with strings too.
Note2: you should check that index (or event constraint) exists for your userId property on :user nodes.
neo4j-jdbc
Code sample for neo4j-jdbc that does work:
Class.forName("org.neo4j.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:neo4j://localhost:7474/");
String removeRelationships = "MATCH (user1:User {id: {1}})-[r:FOLLOW]->(users:User) " +
"WHERE users.id in {2} " +
"DELETE r";
try (final PreparedStatement stmt = connection.prepareStatement(removeRelationships)) {
stmt.setObject(1, "1");
stmt.setObject(2, new ArrayList<Integer>() {{
add("2");
add("3");
}});
stmt.executeQuery();
}

Elasticsearch: bulk update multiple documents saved in a Java String?

I can create the following string saved in a Java String object called updates.
{ "update":{ "_index":"myindex", "_type":"order", "_id":"1"} }
{ "doc":{"field1" : "aaa", "field2" : "value2" }}
{ "update":{ "_index":"myindex", "_type":"order", "_id":"2"} }
{ "doc":{"field1" : "bbb", "field2" : "value2" }}
{ "update":{ "_index":"myindex", "_type":"order", "_id":"3"} }
{ "doc":{"field1" : "ccc", "field2" : "value2" }}
Now I want to do bullk update within a Java program:
Client client = getClient(); //TransportClient
BulkRequestBuilder bulkRequest = client.prepareBulk();
//?? how to attach updates variable to bulkRequest?
BulkResponse bulkResponse = bulkRequest.execute().actionGet();
I am unable to find a way to attach the above updates variable to bulkRequest before execute.
I notice that I am able to add UpdateRequest object to bulkRequest, but it seems to add only one document one time. As indicated above, I have multiple to-be-updated document in one string.
Can someone enlighten me on this? I have a gut feel that I may do things wrong way.
Thanks and regards.
The following code should work fine for you.
For each document updation , you need to create a separate update request as below and keep on adding it to the bulk requests.
Once the bulk requests is ready , execute a get on it.
JSONObject obj = new JSONObject();
obj.put("field1" , "value1");
obj.put("field2" , "value2");
UpdateRequest updateRequest = new UpdateRequest(index, indexType, id1).doc(obj.toString());
BulkRequestBuilder bulkRequest = client.prepareBulk();
bulkRequest.add(updateRequest);
obj = new JSONObject();
obj.put("fieldX" , "value1");
obj.put("fieldY" , "value2");
updateRequest = new UpdateRequest(index, indexType, id2).doc(obj.toString());
bulkRequest = client.prepareBulk();
bulkRequest.add(updateRequest);
bulkRequest.execute().actionGet();
I ran into the same problem where only 1 document get updated in my program. Then I found the following way which worked perfectly fine. This uses spring java client. I have also listed the the dependencies I used in the code.
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.index.query.QueryBuilder;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.elasticsearch.core.query.UpdateQueryBuilder;
private UpdateQuery updateExistingDocument(String Id) {
// Add updatedDateTime, CreatedDateTime, CreateBy, UpdatedBy field in existing documents in Elastic Search Engine
UpdateRequest updateRequest = new UpdateRequest().doc("UpdatedDateTime", new Date(), "CreatedDateTime", new Date(), "CreatedBy", "admin", "UpdatedBy", "admin");
// Create updateQuery
UpdateQuery updateQuery = new UpdateQueryBuilder().withId(Id).withClass(ElasticSearchDocument.class).build();
updateQuery.setUpdateRequest(updateRequest);
// Execute update
elasticsearchTemplate.update(updateQuery);
}

Invalid Resource Id when batch inserting

I am doing a batch insert into the Google Calendar using the .NET API. I have the following code.
var request = new BatchRequest(calendarService);
request.Queue<Event>(
calendarService.Events.Insert(
new Event
{
Id = String.Format("yot-{0}", item.AppointmentId),
Summary = item.Title,
Description = item.Description,
Start = new EventDateTime() { DateTime = item.Date },
End = new EventDateTime() { DateTime = item.Date.AddHours(item.Length) }
}, calendar.Id),
(content, error, i, message) =>
{
//Log error
});
request.ExecuteAsync();
When I execute and try and insert I get the error "Invalid resource id". What does this error mean?
You have to follow the guidelines defined here : https://developers.google.com/google-apps/calendar/v3/reference/events/insert
Basically, the id has to be between 5 and 1024 characters long and consist solely from characters in this alphabet : 0123456789abcdefghijklmnopqrstuv.
Try with a simple Guid.NewGuid() or use a Base32 Encoder if you don't want random IDs

Resources