2016-11-01 8 views
1

Я пытаюсь найти человек, которые были рядом до последнего места пользователя за последние 24 часа для простой рекомендации двигателя. Мой набор данных просто для целей тестирования:Найти люди, которые были рядом с последним местоположением пользователя

enter image description here

Что случилось с моим запросом? Он возвращает пользователя Айсе несколько раз, но я не хочу, чтобы тот же человек дважды или больше.

Вот мои запросы:

var neo4j = require('neo4j-driver').v1; 
var driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j")); 
var session = driver.session(); 

function runQuery(query) { 

    session.run(query, {}).then(function(result){ 

     console.log("finish") 

     result.records.forEach(function(record) { 
      console.log(record._fields) 
     }) 

    }).catch(console.log); 
} 

//runQuery("MATCH (n) DETACH DELETE n") 


function newUser(user) { 
    runQuery("CREATE (:User{name:'"+user+"'})") 
} 

function newLocation(user, lat, lon) { 
    var q = 
"MATCH (u:User{name:'"+user+"'}) "+ 
"CREATE (l:Location{lat: "+lat+", lon: "+lon+", created_at: TIMESTAMP()}) "+ 
"CREATE (u)-[:HAVE_BEEN]->(l) " 
    runQuery(q) 
} 

/* 
newUser("Ozgur") 
newUser("Fatma") 
newUser("Ayse") 
*/ 

/* 
newLocation("Ozgur", 38.134972, 26.96681) 
newLocation("Ozgur", 37.239972, 25.96681) 
newLocation("Ozgur", 38.334972, 16.96681) 
*/ 

/* 
newLocation("Ayse", 38.294972, 26.76681) 
newLocation("Ayse", 37.639972, 25.66681) 
newLocation("Ayse", 35.134972, 18.96681) 
*/ 

/* 
newLocation("Fatma", 31.114972, 21.76681) 
newLocation("Fatma", 31.139972, 21.66681) 
*/ 

function findUserRecommendation(user) { 
    // get user recommendations 
    var q = 
"MATCH "+ 

//get user locations for last 24 hours (me_loc) 
"(me:User{name:'"+user+"'})-[:HAVE_BEEN]->(me_loc:Location), " + 

// strangers (recommendations) 
"(l:Location)<-[:HAVE_BEEN]-(stranger:User) " + 

"WHERE "+ 
    //except me 
    "NOT me = stranger "+ 

    // nearest location algorithm based on KM 
    "AND 2 * 6371 * "+ 
    "asin("+ 
     "sqrt("+ 
      "haversin(radians(me_loc.lat - l.lat)) + "+ 
      "cos(radians(me_loc.lat)) * "+ 
      "cos(radians(l.lat)) * haversin(radians(me_loc.lon - l.lon))"+ 
     ")"+ 
    // 500 km 
    ") < 500 " + 

    // last 24 hours of they location 
    //"AND l.created_at > (TIMESTAMP() - 604800) "+ 

    // last 24 hours of user's location 
    //"AND me_loc.created_at > (TIMESTAMP() - 604800)" + 

// return every stranger's name and last location once 
// but returning Ayse's name and different location more than once 
"RETURN DISTINCT stranger.name, l.lat, l.lon" 
    runQuery(q) 
} 

findUserRecommendation("Ozgur") 

ответ

2

DISTINCT вне агрегации только гарантирует, что вы не будете получать повторяющиеся строки результата, она не ограничивает вас в первой строке для каждого элемента DISTINCT (это на самом деле применяется ко всем неагрегированным элементам в строке как единое целое, подобно использованию кортежа в качестве ключа). Вам нужно будет заполнить lat/long, а затем выяснить, какой из них сохранить. Предполагая, что вы просто хотите какой-либо одной широты/долготы, попробуйте это вместо вашего возвращения линии:

WITH stranger, COLLECT(l) AS locs 
WITH stranger, HEAD(locs) AS l 
RETURN stranger.name, l.lat, l.lon 

Вы можете заменить HEAD() вызов с REDUCE(), если вы хотите, чтобы выбрать один широту/долготу на основе конкретных критериев , как самые последние или самые близкие.

+0

Я пойду с REDUCE(), спасибо за ответ. – Ozgur

Смежные вопросы