blob: 2b7b2c5c1aff253102c452c47c04754aa9ac40c3 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#include <iostream>
#include "ignite/ignite.h"
#include "ignite/ignition.h"
#include "ignite/examples/organization.h"
#include "ignite/examples/person.h"
using namespace ignite;
using namespace cache;
using namespace query;
using namespace examples;
/** Organizations cache name. */
const char* ORG_CACHE = "Organization";
/** Organizations type name. */
const char* ORG_TYPE = "Organization";
/** Persons cache name. */
const char* PERSON_CACHE = "Person";
/** Persons type name. */
const char* PERSON_TYPE = "Person";
/**
* Example for SQL fields queries based on all employees working for a specific
* organization (query uses distributed join).
*
* Note that SQL Fields Query can only be performed using fields that have been
* listed in "QueryEntity" been of the config.
*/
void DoSqlQueryWithDistributedJoin()
{
Cache<PersonKey, Person> cache = Ignition::Get().GetCache<PersonKey, Person>(PERSON_CACHE);
// SQL clause query which joins on 2 types to select people for a specific organization.
SqlFieldsQuery qry(
"select firstName, lastName from Person "
"inner join \"Organization\".Organization as org "
"where Person.orgId = org._key "
"and lower(org.name) = lower(?)");
qry.AddArgument<std::string>("ApacheIgnite");
// Enable distributed joins for query.
qry.SetDistributedJoins(true);
QueryFieldsCursor cursor = cache.Query(qry);
// Printing first result set.
std::cout << "Following people are 'ApacheIgnite' employees (distributed join): " << std::endl;
while (cursor.HasNext())
{
QueryFieldsRow row = cursor.GetNext();
std::string firstName = row.GetNext<std::string>();
std::string lastName = row.GetNext<std::string>();
std::cout << firstName << " " << lastName << std::endl;
}
std::cout << std::endl;
qry.ClearArguments();
qry.AddArgument<std::string>("Other");
cursor = cache.Query(qry);
// Printing second result set.
std::cout << "Following people are 'Other' employees (distributed join): " << std::endl;
while (cursor.HasNext())
{
QueryFieldsRow row = cursor.GetNext();
std::string firstName = row.GetNext<std::string>();
std::string lastName = row.GetNext<std::string>();
std::cout << firstName << " " << lastName << std::endl;
}
std::cout << std::endl;
}
/**
* Example for SQL-based fields queries that return only person name and company it works in.
*
* Note that SQL Fields Query can only be performed using fields that have been
* listed in "QueryEntity" been of the config.
*/
void DoSqlQueryWithJoin()
{
Cache<PersonKey, Person> cache = Ignition::Get().GetCache<PersonKey, Person>(PERSON_CACHE);
// Execute query to get names of all employees.
std::string sql(
"select concat(firstName, ' ', lastName), org.name "
"from Person inner join \"Organization\".Organization as org "
"on Person.orgId = org._key");
QueryFieldsCursor cursor = cache.Query(SqlFieldsQuery(sql));
// Print persons' names and organizations' names.
std::cout << "Names of all employees and organizations they belong to: " << std::endl;
// In this particular case each row will have two elements with full name
// of an employees and their organization.
while (cursor.HasNext())
{
QueryFieldsRow row = cursor.GetNext();
std::string person = row.GetNext<std::string>();
std::string organization = row.GetNext<std::string>();
std::cout << person << " is working in " << organization << std::endl;
}
std::cout << std::endl;
}
/**
* Example for SQL-based fields queries that uses SQL functions.
*
* Note that SQL Fields Query can only be performed using fields that have been
* listed in "QueryEntity" been of the config.
*/
void DoSqlQueryWithFunction()
{
Cache<PersonKey, Person> cache = Ignition::Get().GetCache<PersonKey, Person>(PERSON_CACHE);
// Execute query to get names of all employees.
QueryFieldsCursor cursor = cache.Query(SqlFieldsQuery(
"select concat(firstName, ' ', lastName) from Person"));
// Print names.
std::cout << "Names of all employees: " << std::endl;
// In this particular case each row will have one element with full name of an employees.
while (cursor.HasNext())
{
std::string person = cursor.GetNext().GetNext<std::string>();
std::cout << person << std::endl;
}
std::cout << std::endl;
}
/**
* Example for SQL queries to calculate average salary for a specific organization.
*
* Note that SQL Fields Query can only be performed using fields that have been
* listed in "QueryEntity" been of the config.
*/
void DoSqlQueryWithAggregation()
{
Cache<PersonKey, Person> cache = Ignition::Get().GetCache<PersonKey, Person>(PERSON_CACHE);
// Calculate average of salary of all persons in ApacheIgnite.
// Note that we also join on Organization cache as well.
SqlFieldsQuery qry(
"select avg(salary) "
"from Person, \"Organization\".Organization as org "
"where Person.orgId = org._key "
"and lower(org.name) = lower(?)");
qry.AddArgument<std::string>("ApacheIgnite");
QueryFieldsCursor cursor = cache.Query(qry);
// Calculate average salary for a specific organization.
std::cout << "Average salary for 'ApacheIgnite' employees: " << std::endl;
while (cursor.HasNext())
{
double salary = cursor.GetNext().GetNext<double>();
std::cout << salary << std::endl;
}
std::cout << std::endl;
}
/**
* Example for SQL queries based on salary ranges.
*
* Note that SQL Query can only be performed using fields that have been
* listed in "QueryEntity" been of the config.
*/
void DoSqlQuery()
{
Cache<PersonKey, Person> cache = Ignition::Get().GetCache<PersonKey, Person>(PERSON_CACHE);
// SQL clause which selects salaries based on range.
SqlFieldsQuery qry(
"select firstName, lastName, salary "
"from Person "
"where salary > ? and salary <= ?");
// Execute queries for salary range 0 - 1000.
std::cout << "People with salaries between 0 and 1000 (queried with SQL query): " << std::endl;
qry.AddArgument(0);
qry.AddArgument(1000);
QueryFieldsCursor cursor = cache.Query(qry);
while (cursor.HasNext())
{
QueryFieldsRow row = cursor.GetNext();
std::string firstName = row.GetNext<std::string>();
std::string lastName = row.GetNext<std::string>();
double salary = row.GetNext<double>();
std::cout << firstName << " " << lastName << " : " << salary << std::endl;
}
std::cout << std::endl;
qry.ClearArguments();
// Execute queries for salary range 1000 - 2000.
std::cout << "People with salaries between 1000 and 2000 (queried with SQL query): " << std::endl;
qry.AddArgument(1000);
qry.AddArgument(2000);
cursor = cache.Query(qry);
while (cursor.HasNext())
{
QueryFieldsRow row = cursor.GetNext();
std::string firstName = row.GetNext<std::string>();
std::string lastName = row.GetNext<std::string>();
double salary = row.GetNext<double>();
std::cout << firstName << " " << lastName << " : " << salary << std::endl;
}
std::cout << std::endl;
}
/**
* Example for TEXT queries using LUCENE-based indexing of people's resumes.
*
* Note that to be able to do so you have to add FULLTEXT index for the 'resume'
* field of the Person type. See config for details.
*/
void DoTextQuery()
{
Cache<PersonKey, Person> cache = Ignition::Get().GetCache<PersonKey, Person>(PERSON_CACHE);
typedef std::vector< CacheEntry<PersonKey, Person> > ResVector;
// Query for all people with "Master" in their resumes.
ResVector masters;
cache.Query(TextQuery(PERSON_TYPE, "Master")).GetAll(masters);
// Query for all people with "Bachelor" in their resumes.
ResVector bachelors;
cache.Query(TextQuery(PERSON_TYPE, "Bachelor")).GetAll(bachelors);
std::cout << "Following people have 'Master' in their resumes: " << std::endl;
// Printing first result set.
for (ResVector::const_iterator i = masters.begin(); i != masters.end(); ++i)
std::cout << i->GetKey().ToString() << " : " << i->GetValue().ToString() << std::endl;
std::cout << std::endl;
std::cout << "Following people have 'Bachelor' in their resumes: " << std::endl;
// Printing second result set.
for (ResVector::const_iterator i = bachelors.begin(); i != bachelors.end(); ++i)
std::cout << i->GetKey().ToString() << " : " << i->GetValue().ToString() << std::endl;
std::cout << std::endl;
}
/**
* Example for scan query based on a predicate.
*/
void DoScanQuery()
{
Cache<PersonKey, Person> cache = Ignition::Get().GetCache<PersonKey, Person>(PERSON_CACHE);
ScanQuery scan;
typedef std::vector< CacheEntry<PersonKey, Person> > ResVector;
ResVector res;
cache.Query(scan).GetAll(res);
// Execute queries for salary ranges.
std::cout << "People with salaries between 0 and 1000 (queried with SCAN query): " << std::endl;
for (ResVector::const_iterator i = res.begin(); i != res.end(); ++i)
{
Person person(i->GetValue());
if (person.salary <= 1000)
std::cout << i->GetKey().ToString() << " : " << person.ToString() << std::endl;
}
std::cout << std::endl;
}
/**
* Populate cache with test data.
*/
void Initialize()
{
Cache<int64_t, Organization> orgCache =
Ignition::Get().GetCache<int64_t, Organization>(ORG_CACHE);
// Clear cache before running the example.
orgCache.Clear();
// Organizations.
Organization org1("ApacheIgnite");
Organization org2("Other");
const int64_t org1Id = 1;
const int64_t org2Id = 2;
orgCache.Put(org1Id, org1);
orgCache.Put(org2Id, org2);
Cache<PersonKey, Person> personCache =
Ignition::Get().GetCache<PersonKey, Person>(PERSON_CACHE);
// Clear cache before running the example.
personCache.Clear();
// People.
// Collocated by 1st organisation:
Person p1(org1Id, "John", "Doe", "John Doe has Master Degree.", 2000);
Person p2(org1Id, "Jane", "Doe", "Jane Doe has Bachelor Degree.", 1000);
PersonKey pKey1 (1, org1Id);
PersonKey pKey2 (2, org1Id);
// Collocated by second organisation:
Person p3(org2Id, "John", "Smith", "John Smith has Bachelor Degree.", 1000);
Person p4(org2Id, "Jane", "Smith", "Jane Smith has Master Degree.", 2000);
PersonKey pKey3 (3, org2Id);
PersonKey pKey4 (4, org2Id);
// Note that in this example we use custom affinity key for Person objects
// to ensure that all persons are collocated with their organizations.
personCache.Put(pKey1, p1);
personCache.Put(pKey2, p2);
personCache.Put(pKey3, p3);
personCache.Put(pKey4, p4);
}
int main()
{
try
{
IgniteConfiguration cfg;
cfg.springCfgPath = "platforms/cpp/examples/query-example/config/query-example.xml";
// Start a node.
Ignite ignite = Ignition::Start(cfg);
std::cout << std::endl;
std::cout << ">>> Cache query example started." << std::endl;
std::cout << std::endl;
// Get organization cache instance.
Cache<int64_t, Organization> orgCache = ignite.GetCache<int64_t, Organization>(ORG_CACHE);
// Get person cache instance.
Cache<PersonKey, Person> personCache = ignite.GetCache<PersonKey, Person>(PERSON_CACHE);
// Populate cache.
Initialize();
// Example for SCAN-based query based on a predicate.
DoScanQuery();
// Example for TEXT-based querying for a given string in peoples resumes.
DoTextQuery();
// Example for SQL-based querying employees based on salary ranges.
DoSqlQuery();
// Example for SQL-based querying employees for a given organization (includes SQL join).
DoSqlQueryWithJoin();
// Example for SQL-based querying employees for a given organization (includes distributed SQL join).
DoSqlQueryWithDistributedJoin();
// Example for SQL-based fields queries that uses SQL functions.
DoSqlQueryWithFunction();
// Example for SQL-based querying to calculate average salary among all employees within a company.
DoSqlQueryWithAggregation();
// Stop node.
Ignition::StopAll(false);
std::cout << std::endl;
std::cout << ">>> Example finished, press 'Enter' to exit ..." << std::endl;
std::cout << std::endl;
std::cin.get();
}
catch (IgniteError& err)
{
std::cout << "An error occurred: " << err.GetText() << std::endl;
return err.GetCode();
}
return 0;
}